IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Mybatis学习 -> 正文阅读

[Java知识库]Mybatis学习

1.简介

1.1 什么是Mybatis?

Mybatis是一款优秀的持久层框架
它支持定制化SQL、存储过程以及高级映射
Mybatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集
Mybatis可以使用简单的XML或注解来配置和映射原生类型、接口和Java的pojo为数据库中的记录

1.2 如何获得Mybatis?

maven仓库

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.2</version>
</dependency>

Github: https://github.com/mybatis/mybatis-3/releases
MyBatis文档网址:https://mybatis.org/mybatis-3/zh/index.html

2. 创建第一个Mybatis程序

2.1 搭建环境

1.新建一个普通的maven项目
2.删除src目录
3.加入maven依赖

    <!-- 导入依赖 -->
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

2.2 创建一个模块

1.编写mybatis的核心配置文件
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- configuration核心配置文件 -->
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 每一个Mapper.xml都需要在Mybatis核心配置文件中注册! -->
    <mappers>
        <mapper resource="com/liu/dao/UserMapper.xml" />
    </mappers>
</configuration>

2.编写mybatis工具类
在这里插入图片描述

// SqlSessionFactory -->sqlSession
public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            // 使用Mybatis第一步:
            // 获取sqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 使用Mybatis第二步:
    // 从 SqlSessionFactory 中获取 SqlSession
    // 既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
    // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
    // 你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

2.3 编写代码

1.编写实体类(一个实体类对应一个表)
在这里插入图片描述

package com.liu.pojo;

//实体类
public class User {
    public int id;
    public String name;
    public String pwd;

    public User() {
    }
    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }
    public int getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    public String getPwd() {
        return pwd;
    }
    public void setId(int id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}

2.编写Dao接口
在这里插入图片描述

public interface UserDao {
    List<User> getUserList();
}

3.编写接口对应的Mapper.xml文件(以前是一个UserDaoImpl对应一个UserDao,现在是一个Mapper.xml文件对应一个UserDao)
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace=绑定一个对应的Dao/Mapper接口,必须一致 -->
<mapper namespace="com.liu.dao.UserDao">

    <!-- select查询语句 -->
    <select id="getUserList" resultType="com.liu.pojo.User">
        select * from mybatis.user
    </select>

</mapper>

2.4 测试

在这里插入图片描述
构造尽量保持规范,在test下建立com.liu.dao,并编写测试类UserDaoTest

public class UserDaoTest {
    @Test
    public void test() {
        // 第一步:获得SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //方式一;getMapper
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        List<User> userlist = userDao.getUserList();
        for (User user : userlist) {
            System.out.println(user);
        }

        // 关闭SqlSession
        sqlSession.close();
    }
}

2.5 注意点

1.每一个Mapper.xml都需要在Mybatis核心配置文件中注册!

    <mappers>
        <mapper resource="com/liu/dao/UserMapper.xml" />
    </mappers>

2.maven由于他的约定大于配置,可能会遇到我们写的配置文件(.xml或者.properties)无法被导出或者生效的问题,解决方案为在pom文件中贴如下代码:

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory><!--所在的目录-->
                <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <!-- filtering选项 false不启用过滤器, *.property已经起到过滤的作用了 -->
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory><!--所在的目录-->
                <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <!-- filtering选项 false不启用过滤器, *.property已经起到过滤的作用了 -->
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

3.空指针问题:可能是重复定义了某变量所致

在这里插入图片描述

3.CRUD

3.1 namespace

namepspace中的包名要和Dao/Mapper接口的包名一致!

在这里插入图片描述

3.2 select

选择,查询语句;

  • id:就是对应的namespace中绑定的Mapper接口中的方法名
  • resultType:sql语句执行后的返回值
  • parameterType:参数类型
  • 通过 #{} 来取传递的参数

编写接口

    //根据ID查询用户
    User getUserById(int id);

编写对应的mapper中的sql语句

    <!-- select查询语句 -->
    <select id="getUserList" resultType="com.liu.pojo.User">
        select * from mybatis.user
    </select>

测试

    @Test
    public void getUserById(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        User user=mapper.getUserById(1);
        System.out.println(user);

        sqlSession.close();
    }

3.3 insert

编写接口

    //插入
    int addUser(User user);

编写对应的mapper中的sql语句

	<!-- 对象中的属性,可以直接取出来 -->
    <insert id="addUser" parameterType="com.liu.pojo.User">
        insert into mybatis.user(id, name, pwd) values (#{id},#{name},#{pwd})
    </insert>

测试

    //增删改查需要提交事务
    @Test
    public void addUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        int res = mapper.addUser(new User(4,"哈哈","123333"));
        if(res>0)
            System.out.println("插入成功!");

        //提交事务
        sqlSession.commit();
        sqlSession.close();
    }

3.4 update

编写接口

    //修改
    int updateUser(User user);

编写对应的mapper中的sql语句

    <update id="updateUser" parameterType="com.liu.pojo.User">
        update mybatis.user set name = #{name}, pwd = #{pwd} where id = #{id}
    </update>

测试

    @Test
    public void updateUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        int res=mapper.updateUser(new User(4,"呵呵","111111"));
        if(res>0)
            System.out.println("修改成功!");

        //提交事务
        sqlSession.commit();
        sqlSession.close();
    }

3.5 delete

编写接口

    //删除
    int deleteUser(int id);

编写对应的mapper中的sql语句

    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id = #{id}
    </delete>

测试

    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        int res=mapper.deleteUser(4);
        if(res>0)
            System.out.println("删除成功");

        // 提交事务
        sqlSession.commit();
        sqlSession.close();
    }

注意点:增删改需要提交事务!!

3.6 万能的Map

假设我们的实体类,或者数据库中的表,字段或者参数过多,则应当考虑使用map。与直接传递对象的区别就在于使用map不一定要获取到所有的属性,而当使用User时,必须将所有的属性包揽在内

1.接口中参数声明为Map形式

    //修改:万能的Map
    int updateUser2(Map<String,Object> map);

2.Mapper中:参数类型是小写的map, 里面的值是map的key

    <!-- 传递的参数为map的key -->
    <update id="updateUser2" parameterType="map">
        update mybatis.user set name= #{name} where id=#{id}
    </update>

3.测试代码

    @Test
    public void updateUser2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        Map<String,Object> map=new HashMap<String, Object>();
        map.put("id",1);
        map.put("name","刘梦豪"); // 最大的区别就在于使用map不需要获取到所有的属性,而当使用User时,必须将所有的属性包揽在内

        mapper.updateUser2(map);
        sqlSession.commit();
        sqlSession.close();
    }

总结

Map传递参数,直接在sql中取出key即可!【parameterType=“map”】
#{key} 即可取到
对象传递参数,直接在sql中取对象的属性即可!【parameterType=“Object”】
#{对象包含的属性名}即可取到

对于方法中只有一个基本类型参数的情况下,可以直接在sql中取到!
#{参数名}
对于方法中多个参数:用Map,或者注解@Param("") 后续会讲到

3.7 模糊查询

1.编写接口

    // 模糊查询
    List<User> getUserLike(String value);

2.编写对应的mapper中的sql语句并测试
方式一:

    <select id="getUserLike" resultType="com.liu.pojo.User">
        select * from mybatis.user where name like #{value}
    </select>

对应的测试代码为:

    @Test
    public void getUserLike(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> userList = mapper.getUserLike("%李%");

        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

方式二:

    <select id="getUserLike" resultType="com.liu.pojo.User">
        select * from mybatis.user where name like "%"#{value}"%"
    </select>

对应的测试代码为:

    @Test
    public void getUserLike(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> userList = mapper.getUserLike("李");

        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

4. 配置分析

4.1 核心配置文件

一般命名为:mybatis-config.xml

configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

4.2 环境配置(environments)

MyBatis 可配置成适应多种环境
但是尽管可以配置多种环境,但每个 SqlSessionFactory 实例只能选择一种环境!
在这里插入图片描述

4.3 属性(properties)

我们可以通过properties来实现引用配置文件,这些属性都是可以外部配置且可动态替换的。既可以在典型的Java属性文件中配置,也可以通过properties元素的子元素来传递(db.properties)

编写一个配置文件
在这里插入图片描述
在核心配置文件中可引入外部配置文件
在这里插入图片描述
如果里面和外面的配置冲突了,优先使用外面的配置
在这里插入图片描述

4.4 类型别名(typeAliases)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
第一种写法:

    <!-- 可以给实体类起别名 -->
    <typeAliases>
        <typeAlias type="com.liu.pojo.User" alias="User"/>
        ...
    </typeAliases>

第二种写法:扫描一个包,每个实体类的默认别名就为这个类的类名,首字母一般小写!(大写也行)

    <!-- 别名为小写类名(首字母大写的话也行) -->
    <typeAliases>
        <package name="com.liu.pojo"/>
    </typeAliases>

第三种写法:注解方式(在第二种写法的基础上,如果要修改名时则使用,如果一三写法同时使用,第一种生效)
直接在类的上面使用注解@Alias(“自定义名称”)

@Alias("hello")
public class User {
    ...
}

4.5 映射器(mappers)

每一个mapper都需要注册,注册mapper有三种方式
方式一:使用相对于类路径的资源引用

<!-- 使用相对于类路径的资源引用 -->
<configuration>
	<mappers>
	 	<mapper resource="com/liu/dao/UserMapper.xml"/>
	 	...
	</mappers>
</configuration>

方式二:使用映射器接口实现类的完全限定类名

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="com.liu.dao.UserMapper"/>
  ...
</mappers>

方式三:使用扫描包进行注入

<mappers>
  <package name="com.liu.dao"/>
  ...
</mappers>

后两种方式的注意点:

  • 接口和他的Mapper配置文件必须同名!
  • 接口和他的Mapper配置文件必须在同一个包下!

5. 生命周期

在这里插入图片描述
SqlSessionFactoryBuilder:

  • 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。

SqlSessionFactory:

  • 说白了就是可以想象为:数据库连接池
  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
  • 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次创建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。
  • 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

SqlSession:

  • 是连接到连接池的一个请求
  • 每个线程都应该有它自己的 SqlSession 实例。
  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
  • 用完之后需要赶紧关闭,否则资源被占用!
    在这里插入图片描述
    这里面的每一个Mapper,就代表一个具体的业务!

6. 结果集映射(resultMap)

当表的字段名与实体类字段名不对应的时候,要进行映射。(在mapper.xml文件中)
实体类对应属性名property,数据库字段名column

    <!-- 结果集映射 -->
    <resultMap id="UserMap" type="user">
        <!-- column为数据库中的字段,property为实体类中的属性 -->
        <!-- 对于本就相同的column和property,可以不写 -->
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="pwd" property="password" />
    </resultMap>

sql语句中的resultType改为resultMap

    <select id="getUserById" resultMap="UserMap">
        select * from mybatis.user where id=#{id}
    </select>

7.日志

如果一个数据库操作出现了异常,我们需要排错。日志就是最好的助手。
一般采用日志工厂来解决。掌握(STDOUT_LOGGING和LOG4J)
在Mybatis中具体使用哪一日志,需要在设置中设定!

7.1 标准的日志工厂实现(STDOUT_LOGGING)

    <settings>
        <!--标准的日志工程实现-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

7.2 Log4j

什么是Log4j?

  • Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件
  • 我们可以控制每一条日志的输出格式
  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

1.先导入log4j依赖

    <dependencies>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

2.在resources下增加文件log4j.properties(可以写成其他的)

log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置;第二行表示日志会被保存在的位置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/liu.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

3.在mybatis核心配置文件中配置log4j为日志实现

    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>

4.简单使用

  • 在需要使用log4j的类中,导入包 import org.apache.log4j.Logger;

  • 获取日志对象,参数为当前类的class

    static Logger logger = Logger.getLogger(UserMapperTest.class);
    
  • 举例

    public class UserMapperTest {
        static Logger logger = Logger.getLogger(UserMapperTest.class);
        @Test
        public void log4jTest(){
            logger.info("info:进入了testLog4j");
            logger.debug("debug:进入了testLog4j");
            logger.error("error:进入了testLog4j");
        }
    }
    

8. 分页

为什么要分页?

  • 减少数据的处理量

limit语法:
对于一个参数的情况就是显示出前n行数据

select * from product limit n;		// 展示[0,n]

limit有两个参数,第一个参数表示从第几行数据开始查(startIndex),第二个参数表示每页的大小(pageSize)

select * from product limit 3,2; //“limit 3,2”表示从第四行数据开始,取两条数据。

1.定义接口

    //分页
    List<User> getUserByLimit(Map<String,Integer> map);

2.在mapper.xml文件实现

    <!-- 结果集映射 -->
    <resultMap id="UserMap" type="user">
        <!-- column为数据库中的字段,property为实体类中的属性 -->
<!--        <result column="id" property="id"/>-->
<!--        <result column="name" property="name"/>-->
        <result column="pwd" property="password" />
    </resultMap>

    <!-- 分页 -->
    <select id="getUserByLimit" parameterType="map" resultMap="UserMap">
        select * from mybatis.user limit #{startIndex},#{pageSize};
    </select>

3.测试

    @Test
    public void getUserByLimit(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        HashMap<String, Integer> map = new HashMap<String, Integer>();
        map.put("startIndex",1);
        map.put("pageSize",2);

        List<User> userlist = mapper.getUserByLimit(map);
        for (User user : userlist) {
            System.out.println(user);
        }

        sqlSession.close();
    }

还有一种分页方式不需要写sql代码,通过RowBounds实现

9. 注解

9.1 注解开发

1.注解形式:(在接口文件里面方法上直接添加注解)

public interface UserMapper {

    @Select("select * from user")
    List<User> getUsers();
}

2.在mybatis-config.xml文件中添加类路径映射,绑定接口

    <!-- 绑定接口 -->
    <mappers>
        <mapper class="com.liu.dao.UserMapper"/>
    </mappers>

本质:利用Java反射
底层:代理
注意: 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-10 12:16:21  更:2021-11-10 12:17:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:33:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码