一、mybatis 概述

mybatis 是一个用Java编写的持久层框架,它使用 ORM 实现了结果集的封装。

ORM(Object Relational Mapping): 对象关系映射。简单来说,就是把数据库表和实体类及实体类的属性对应起来,让开发者操作实体类就实现操作数据库表,它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等复杂过程。mybatis就是ORM的一种实现方式,简单来说就是将数据库中查询出的数据映射到对应的实体中。

二、mybatis的操作步骤

通过 Resources 的 getResourceAsStream 告诉了mybatis我们编写的核心配置文件的位置;
mybatis 就可以找到数据库的连接信息,也同时找到编写的 sql 语句的地方;
然后可以将其解析按照某种规则存放起来,我们通过调用接口代理的方式执行方法时,可以找到对应方法上的 sql 语句然后执行将结果封装返回给我们。

1、导入 mybatis 依赖

maven项目,在pom.xml中添加依赖;非maven项目,添加jar包,这里不再赘述。

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.5</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.18</version>
</dependency>

2、定义 mybatis 核心配置文件

核心配置文件为 mybatis-config.xml 文件,当然,文件名称可以自定义。

<?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>
    <!--  JavaBean类型自动映射扫描包配置 Java类型别名  -->
    <typeAliases>
        <package name="com.brok1n.web.java.springmvcdemo1.bean"/>
        <!--<typeAlias alias="User" type="com.brok1n.web.java.springmvcdemo1.bean.User" />-->
    </typeAliases>

    <environments default="development">
        <!-- 数据库环境 -->
        <environment id="development">
            <!-- 使用JDBC使用管理 -->
            <transactionManager type="JDBC"/>
            <!-- 数据源配置 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 映射器 -->
    <mappers>
        <mapper resource="mybatis/UserMapper.xml"/>
    </mappers>
</configuration>

3、编写实体类

public class User {    
	private Integer uid;    
	private String username;    
	private String password;    
	
	public Integer getUid(){
        return uid;
    }

    public void setName(Integer uid){
        this.uid = uid;
    }

	public String getUsername(){
        return username;
    }

    public void setUsername(String username){
        this.username = username;
    }

	public String getPassword(){
        return password;
    }

    public void setPassword(String password){
        this.password = password;
    }
}

4、定义mapper 接口及 mapper.xml文件

方法的名称与 userMapper.xml 的 sql id名称要保持一致。

mapper 接口:

public interface UserMapper {
    List<UserEntity> getByUsers();
}

mapper.xml文件:

<?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">
<mapper namespace="com.qize.mapper.UserMapper">
    <select id="getByUsers" resultType="com.qize.entity.User">
        select * from qize_users
  </select>
</mapper>

5、测试代码

//1.关联主配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2.解析配置文件
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
//3.创建会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.可以采用接口代理的方式
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> all = mapper.getByUsers();
System.out.println(all);
//5.释放资源
sqlSession.close();

三、SqlSessionFactoryBuilder 深度解析

//1.关联主配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2.解析配置文件
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);

1、build(InputStream in) 方法解析

(1)借助 Dom4j 的来解析了 xml 文件, 将 environments 解析工作分发给了 parseEnvironment(Element environments)。
(2)将 mappers 的解析工作分发给了 parseMapper(Element mapper)

2、parseEnvironment(Element environments)方法解析

(1)主要解析了连接数据库的参数们,并且创建了数据库连接池。
(2)将解析好的连接池放入 configuration 对象中。

3、parseMapper(Element mapper) 方法解析

(1)解析出用户配置的 package 找到 sql 语句所在接口的文件夹,交给 initMapper 来处理。
(2)递归找到这个包下所有的.class 文件,并且获取到接口的全类名, 然后交给 initMapper 来处理。
(3)initMapper 通过反射获取类中的每一个方法,将方法交给一个专门解析方法上的注解的工具类 ParseMapper 的 parse 方法处理,处理完后将其放到 configuration 中的 mappers 的集合中。
(4)ParseMapper 的 parse 方法做的工作,首先拿到方法上的注解,得到用户填入的 sql 语句。然后处理 sql 语句#{参数}的这些数据, 然后将参数的顺序保存起来, 用来后期设置参数的数据做准备, 一个方法对应一个 Mapper 对象。然后再根据结果类型, 判断是什么类型相关的操作,方便后期执行对应的 sql 语句。

四、深度分析解析SqlSessionFacotry干的核心工作

//3.创建会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();

1、SqlSession openSession() 方法解析

在这个方法创建了 DefaultSqlSession 对象,并传入封装好的 configuration,默认的事务管理器。
默认通过openSession事务是开启的等等相关的参数

五、深度分析解析SqlSession干的核心工作

//4.可以采用接口代理的方式
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

主要使用的动态代理的技术创建接口的实现类,内部主要整合了 sqlId 和参数,省去用户自己拼 sqlId 拼错的风险。
也同时解决用户手动合参数的麻烦,但是最终工作的还是 selectOne、selectList 以及 update0 这些方法。