Mybatis轻松入门(仅要求会用看着一个就够了,略过源码分析部分即可)

一、概念

**Mybatis简介:**Mybatis是一款优秀的基于ORM半自动轻量级持久层框架,他支持定制化SQL、存储过程及高级映射。

  1. ORM:全称Object Relation Mapping:对象关系映射的缩写(将程序员直接操作数据库的工作转换为操作对象,ORM框架将这些面向对象的操作转换为底层的SQL操作)
  2. 半自动:全自动框架程序员将失去对SQL进行优化的权利,半自动支持我们去编写优化SQL
  3. 轻量级:Mybatis在启动时需要的资源较少

**Mybatis优势:**Mybatis是一个半自动化的持久层框架。对开发人员而言,核心SQL还需要自己优化,SQL和java编码分开,功能边界清晰,一个专注业务一个专注数据。

二、快速入门

Mybatis官网地址

1.开发步骤

  1. 添加Mybatis依赖
  2. 创建User数据表
  3. 编写User实体类
  4. 编写映射配置文件UserMapper.xml
  5. 编写核心配置文件sqlMapConfig.xml
  6. 编写测试类

2.环境搭建

2.1.导入Mybatis的坐标和其他坐标

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
        <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
        </dependency>
        <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.17</version>
        </dependency>
        <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
        </dependency>
</dependencies>

2.2.创建User表

在这里插入图片描述

2.3.编写实体

public class User {    
        private Integer id;    
        private String username;   
        //省略get,set方法
}

2.4.编写UserMapper配置文件

<?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="user">
        <!--namespace:名称空间:与ID组成SQL的唯一标识-->
        <!--查询用户-->
        <select id="findAll" resultType="com.myf.pojo.User">
                select * from user
        </select>
        <!--添加用户-->
        <select id="saveUser" parameterType="com.myf.pojo.User">
                insert into user values (#{id},#{username})
        </select>
        <!--修改用户-->
        <update id="updateUser" parameterType="com.myf.pojo.User">
                /*参数对应的是实体类中get方法方法名首字母小写获得的*/
                update user set username=#{username} where id = #{id}
        </update>
        <!--删除用户-->
        <delete id="deleteUser" parameterType="java.lang.Integer">
                delete from user where id = #{id}
        </delete>
</mapper>

2.5.编写核心配置文件

<?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>
    <!--environments运行环境-->
    <environments default="development">
        <!--生产环境-->
        <environment id="">
            <transactionManager type=""></transactionManager>
            <dataSource type=""></dataSource>
        </environment>
        <!--开发环境-->
        <environment id="development">
            <!--表示当前事务交由JDBC进行管理-->
            <transactionManager type="JDBC"></transactionManager>
            <!--表示使用mybatis提供的连接池,UNPOOLED代表不使用连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///zdy_mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="******"/>
            </dataSource>
        </environment>
    </environments>


    <!--引入映射配置文件-->
    <mappers>
        <mapper resource="UserMapper.xml"></mapper>
    </mappers>
</configuration>

2.6.编写测试代码

@Test
public void test1() throws IOException {
    //1.Resources工具类,配置文件的加载,把配置文件加载成字节输入流
    InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
    //2.解析配置文件,并创建了sqlSessionFactory对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    //3.生产sqlSession
    //默认开启一个事务但事务不会自动提交,需要手动提交事务。可以设置.openSession(true);自动提交事务
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //4.sqlSession调用方法:查询所有selectList,查询单个selectOne,添加insert,修改update,删除delete
    List<Object> objects = sqlSession.selectList("user.findAll");
    for (Object o : objects) {
        System.out.println(o);
    }
}

三、Mybatis核心配置文件分析

Mybatis核心配置文件层级关系

1.Mybatis常用标签

1.1 environments标签

数据库环境配置,支持多环境配置

在这里插入图片描述

transactionManager类型有两种

  1. JDBC:这个配置就是直接使用了JDBC的提交和回滚,它依赖于从数据源得到的连接来管理事务作用域。
  2. MANAGER:不会提交和回滚一个连接,而是让容器来管理实务的整个生命周期。

dataSource数据源*类型有三种

  1. UNPOOLED:每次请求获取新的连接结束后关闭连接。
  2. POOLED:表示使用连接池
  3. JNDI:JNDI—数据源的这个实现是为了与EJB或应用服务器这样的容器一起使用,这些容器可以集中或外部配置数据源,并在JNDI上下文中放置对数据源的引用。(不重要)

1.2 mappers标签

Java doesn’t really provide any good means of auto-discovery in this regard, so the best way to do it is to simply tell MyBatis where to find the mapping files.

Java实际上并没有提供任何好的自动发现方法,所以最好的方法是简单地告诉MyBatis在哪里找到映射文件。

<mappers>
    <!-- Using classpath relative resources -->
    <!-- 使用相对于类路径引用 -->
    <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
    <!-- Using url fully qualified paths -->
    <!-- 使用完全限定资源定位符 -->
    <mapper url="file:///var/mappers/AuthorMapper.xml"/>
    <!-- Using mapper interface classes -->
    <!-- 使用类的完全限定名 -->
	<mapper class="org.mybatis.builder.AuthorMapper"/>
    <!-- Register all interfaces in a package as mappers -->
    <!-- 将包内的映射器接口实现全部注册为映射器 -->
    <package name="org.mybatis.builder"/>
</mappers>

2.配置文件深入

2.1 Properties标签

习惯将数据源的配置信息单独抽取成一个properties文件

编写jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///zdy_mybatis
jdbc.username=root
jdbc.password=110110110

sqlMapConfig引入jdbc.properties

<properties resource="jdbc.properties"></properties>

<!--dataSource前后省略了environments标签-->
<dataSource type="POOLED">
    <property name="driver" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</dataSource>

测试代码正常执行,成功读取到了配置信息

2.2 typeAliases标签

为java类型设置短的别名

<typeAliases>
    <!--给单独的实体起别名-->
    <typeAlias type="com.myf.pojo.User" alias="user"></typeAlias>
    <!--批量起别名,别名为类名:别名不区分大小写-->
    <package name="com.myf.pojo"/>
</typeAliases>

常用基本类型别名配置

integerInteger
doubleDouble
floatFloat
booleanBoolean
。。。。。。。。

3. mapper.xml

3.1 动态SQL之if

<!--多条件组合查询:演示If-->
<select id="findByCondition" parameterType="user" resultType="user">
    select * from USER
    <where>
        <if test="id != null">
            and id = #{id}
        </if>
        <if test="username != null and username!=''">
            and username = #{username}
        </if>
    </where>
</select>

3.2 动态SQL之forEach

<!--多值查询:演示forEach-->
<select id="findByIds" parameterType="list" resultType="user">
    select * from user
    <where>
        /*collection:array数组,list集合,open开始,close结束,item元素,separator分割*/
        <foreach collection="array" open="id in (" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </where>
</select>

3.3 sql映射抽取

<!--抽取SQL片段-->
<sql id="selectUser">
	select * from USER 
</sql>

<select id="findAll" resultType="user">
    <include refid="selectUser"></include>
</select>

四.Mybatis的Dao层实现

1. 传统开发方式

编写接口

public interface UserDao {
    //查询所有用户
    public List<User> findAll() throws IOException;
}

编写实现类

public class UserDaoImpl implements UserDao {
    @Override
    public List<User> findAll() throws IOException {
        //返回文件流
        InputStream resourceAsSteam = Resources.getResourceAsStream("sqlMapConfig.xml");
        //构建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsSteam);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> list = sqlSession.selectList("user.findAll");
        return list;
    }
}

编写测试类

@Test
public void test5() throws IOException {
    UserDao userDao = new UserDaoImpl();
    List<User> users = userDao.findAll();
    for (User o : users) {
        System.out.println(o);
    }
}

2. 代理开发方式

只需要编写dao接口

mapper接口需要遵循以下规范

  1. Mapper.xml文件中的namespace与mapper接口的全限定名相同。
  2. Mapper接口方法名与Mapper.xml中定义的每个SQL的parameterType类型相同。
  3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个parameterType的类型相同。
  4. Mapper接口方法的返回值类型和Mapper.xml中定义的每个resultType的类型相同。

修改接口和配置文件的对应关系

在这里插入图片描述

测试类

@Test
public void test5() throws IOException {
    InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserDao mapper = sqlSession.getMapper(UserDao.class);
    List<User> users = mapper.findAll();
    for (User user : users) {
        System.out.println(user);
    }
}

五、Mybatis复杂映射开发

查询多个表,resultType(自动按照字段名和属性名完成映射封装)不满足需求,使用resultMap手动配置实体属性与表字段的映射关系

1. 一对一查询

查询订单并带出用户信息

编写接口

public interface UserMapper {
    //查询订单的同时还查询该订单所属的用户
    public List<Order> findOrderAndUser();
}

编写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.myf.mapper.UserMapper">

    <resultMap id="orderMap" type="com.myf.pojo.Order">
        <result property="id" column="id"></result>
        <result property="orderTime" column="orderTime"></result>
        <result property="total" column="total"></result>
        <result property="uid" column="uid"></result>

        <association property="user" javaType="com.myf.pojo.User">
            <result property="id" column="uid"></result>
            <result property="username" column="username"></result>
            <result property="password" column="password"></result>
            <result property="birthday" column="birthday"></result>
        </association>
    </resultMap>

    <!--resultMap手动配置实体属性与表字段的映射关系-->
    <select id="findOrderAndUser" resultMap="orderMap">
        SELECT * FROM orders o,user u WHERE o.uid = u.id
    </select>
</mapper>

编写测试类

public class MybatisTest {
    @Test
    public void test1() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<Order> orders = mapper.findOrderAndUser();
        for (Order order : orders) {
            System.out.println(order);
        }
    }
}

2. 一对多查询

查询出全部用户信息并带出订单信息

XML配置

<resultMap id="userMap" type="com.myf.pojo.User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <result property="password" column="password"/>
    <result property="birthday" column="birthday"/>

    <collection property="orderList" ofType="com.myf.pojo.Order">
        <id property="id" column="oid"/>
        <result property="orderTime" column="ordertime"/>
        <result property="total" column="total"/>
        <result property="uid" column="uid"/>
    </collection>
</resultMap>

<select id="findUserAndOrder" resultMap="userMap">
    SELECT
        u.*,
        o.id oid,
        o.ordertime,
        o.total,
        o.uid
    FROM
    USER u
    LEFT JOIN orders o ON u.id = o.uid
</select>

3. 多对多查询

多对多在数据库中的体现是添加一个用户角色关联表

查询所有用户查询出每个用户关联的角色

<resultMap id="userRoleMap" type="com.myf.pojo.User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <result property="password" column="password"/>
    <result property="birthday" column="birthday"/>

    <collection property="roleList" ofType="com.myf.pojo.Role">
        <id property="id" column="sid"/>
        <result property="roleName" column="roleName"/>
        <result property="roleDesc" column="roleDesc"/>
    </collection>
</resultMap>

<select id="findUserAndRole" resultMap="userRoleMap">
    SELECT
    u.*,
    sr.id sid,
    sr.rolename roleName,
    sr.roleDesc roleDesc
    FROM
    USER u
    LEFT JOIN sys_user_role ur ON u.id = ur.userid
    LEFT JOIN sys_role sr ON ur.roleid = sr.id
</select>

六、Mybatis注解开发

  • @Insert:实现新增
  • @Update:实现更新
  • @Delete:实现删除
  • @Select:实现查询
  • @Result:实现结果集封装
  • @Results:可以与
  • @Result 一起使用,封装多个结果集
  • @One:实现一对一结果集封装
  • @Many:实现一对多结果集封装

1. 基本注解开发

编写接口

@Insert("insert into user(id,username) values(#{id},#{username})")
public void addUser(User user);

@Update("update user set username = #{username} where id = #{id}")
public void updateUser(User user);

@Select("select * from user")
public List<User> selectUser();

@Delete("delete from user where id = #{id}")
public void deleteUser(Integer id);

2.复杂映射开发

在这里插入图片描述

2.1 一对一查询

查询订单并带出用户信息

@Results({
    @Result(property = "id",column = "id"),
    @Result(property = "orderTime",column = "orderTime"),
    @Result(property = "total",column = "total"),
    @Result(property = "user",column = "uid",javaType = User.class,one = @One(select = "com.myf.mapper.UserMapper.findUserById"))
})
@Select("select * from Orders")
public List<Order> findOrderAndUser2();

@One执行的是User的查询

@Select("select * from user where id = #{id}")
public User findUserById(Integer id);

2.2 一对多查询

查询出全部用户信息并带出订单信息

@Results({
    @Result(property = "id",column = "id"),
    @Result(property = "username",column = "username"),
    @Result(property = "password",column = "password"),
    @Result(property = "birthday",column = "birthday"),
    @Result(property = "orderList",column = "id",javaType = List.class,many = @Many(select = "com.myf.mapper.OrderMapper.findOrderByUid"))
})
@Select("select * from user")
public List<User> findUserAndOrder2();

@Many执行的Order查询是

@Select("select * from orders")
public List<Order> findOrderByUid(Integer id);

2.3 多对多查询

多对多在数据库中的体现是添加一个用户角色关联表

查询所有用户查询出每个用户关联的角色

@Select("select * from user")
@Results({
    @Result(property = "id",column = "id"),
    @Result(property = "username",column = "username"),
    @Result(property = "password",column = "password"),
    @Result(property = "birthday",column = "birthday"),
    @Result(property = "roleList",column = "id",javaType = List.class,many = @Many(select = "com.myf.mapper.RoleMapper.findRoleByUid"))
})
public List<User> findUserAndRole2();

@Many执行的Role查询是

@Select("select * from sys_role r, sys_user_role ur where r.id = ur.roleid and ur.userid = #{id}")
public List<Role> findRoleByUid(Integer id);

七、Mybatis缓存

缓存就是内存中的数据,对数据库的查询结果的保存,使用缓存,我们可以避免频繁的与数据库尽心交互,进而提高响应速度。

Mybatis也提供了对缓存的支持,分为一级缓存和二级缓存。

在这里插入图片描述

  1. 一级缓存是sqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同sqlSession之间的缓存数据区域HashMap是互不影响的。
  2. 二级缓存是mapper级别的缓存,多个sqlSession去操作同一个Mapper的sql语句,多个sqlSession可以共用二级缓存,二级缓存是跨sqlSession的。

1.一级缓存

Mybatis中一级缓存默认是开启的

验证一级缓存的存在

@Test
public void firstLevelCache(){
    //第一次查询ID为1的用户
    User user1 = userMapper.findUserById(1);
    //第二次查询ID为1的用户
    User user2 = userMapper.findUserById(1);
    System.out.println(user1==user2);
}

在这里插入图片描述

通过调试日志可知只有第一次访问了数据库,切user1和user2是同一个对象的引用(内存地址相同)

@Test
public void firstLevelCache(){
    //第一次查询ID为1的用户
    User user1 = userMapper.findUserById(1);
    User user = new User();
    user.setId(1);
    user.setUsername("moyifeng");
    userMapper.updateUser(user);
    //第二次查询ID为1的用户
    User user2 = userMapper.findUserById(1);
    System.out.println(user1==user2);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qsSO88rR-1605459206131)(.\D12__Mybatis相关概念.assets\image-20201115202913954.png)]

通过日志信息可知,在发生增删操作之后,再次发生相同查询会访问数据库

总结

  1. 第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息,将用户信息存储到一级缓存中。
  2. 如果中建sqlSession执行了增删改操作,则会清空sqlSession中的一级缓存,这样做的目的是为了让缓存中存储的是最新的信息,避免脏读。
  3. 第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有直接从缓存中获取用户信息。

2.一级缓存源码分析

问题:

一级缓存是什么?

一级缓存什么时候创建、一级缓存的工作流程是怎样的?

分析

在这里插入图片描述

  1. 首先看代码,sqlSession为创建的执行sql的对象,因此从这作为入口找到clearCache()与缓存相关。
  2. sqlSession是接口找到其实现类DefaultSqlSession。
  3. DefaultSqlSession中clearCache执行的是Executor.clearLocalCache()。
  4. 找到Executor的实现类BaseExecutor。
  5. 看到其执行的第一句话就是PerpetualCache.clear()。
  6. PerpetualCache的clear方法中执行的是this.cache.clear()。看其属性this.cache就是一个HashMap。cache.clear()就是map.clear()
  7. 由以上分析可知,Mybatis一级缓存本质就是一个HashMap实现的。
  8. Mybatis到底是如何创建使用的一级缓存呢,我们想到Mybatis所有的查询都是通过Executor执行的找到他,发现其中还有一个缓存相关接口createCacheKey。
  9. 找到其实现类,其执行的方法就是创建了一个可以唯一确定查询的key,那么什么时候执行的呢,由之前的自定义Mybatis框架我们想到query方法。
  10. 具体看下图

在这里插入图片描述

3.二级缓存

二级缓存的原理和一级缓存原理一样,第一次查询,会将数据放入缓存中,然后第二次查询则会直接去缓存中取。但是一级缓存是基于sqlSession的,而二级缓存是是基于mapper的namespace的,也就是说多个sqlSession可以共享一个mapper中的二级缓存区域,并且如果两个mapper的namespace相同,即使是两个mapper,那么这两个mapper中执行sql查询到的数据也将存储在相同的二级缓存区域中。

3.1 开启二级缓存

全局配置文件sqlConfig.xml中

<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

其次在UserMapper.xml文件中开启缓存

<!--开启二级缓存-->
<cache></cache>

注解方式在类上加注解

@CacheNamespace
public interface UserMapper {

3.2 测试效果

@Test
public void secondLevelCache(){
    SqlSession sqlSession = sqlSessionFactory.openSession();
    SqlSession sqlSession1 = sqlSessionFactory.openSession();
    SqlSession sqlSession2 = sqlSessionFactory.openSession();

    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
    UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);

    User user = userMapper.findUserById(1);
    sqlSession.close();//清空一级缓存
    User user1 = userMapper1.findUserById(1);

    User user2 =new User();
    user2.setId(1);
    user2.setUsername("moyifeng1");
    userMapper2.updateUser(user2);
    sqlSession2.commit();

    User user11 = userMapper1.findUserById(1);
    System.out.println(user==user1);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ny0MoD8L-1605459206132)(.\D12__Mybatis相关概念.assets\image-20201115222250870.png)]

3.3 其他配置

userCache

单独设置该sql是否禁用二级缓存,在statement中设置useCache=false可以金融当前select语句的二级缓存,默认为true

<select id="selectUserByUserId" useCache="false"resultType="com.myf.pojo.User" parameterType="int">
	select * from user where id=#{id}
</select>

注解方式

@Options(useCache = false)
@Select("select * from user")
public List<User> selectUser();

flushCache

在执行增删改操作后刷新缓存,默认是开启的,所以一般不用操作,设置成false则不会刷新缓存,设置方式参考userCache

4. Mybatis使用Redis实现二级缓存

4.1 二级缓存源码概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CMfGfBkw-1605459206135)(.\D12__Mybatis相关概念.assets\image-20201115224112362.png)]

不管是Mybatis自己实现的二级缓存还是自定义二级缓存都是实现上方标红的Cache接口。

PerpetualCache是Mybatis的默认实现类,打开该类可以看到其底层数据结构就是HashMap。

前面我们声明使用了二级缓存

@CacheNamespace
public interface UserMapper {

上面的写法其实是下面的缩写

@CacheNamespace(implementation = PerpetualCache.class)
public interface UserMapper {

4.2 二级缓存整合Redis

上面学习了Mybatis自带的二级缓存,但是这个缓存是单服务器工作,无法实现分布式缓存。

为了解决这个问题,就得找一个分布式缓存,专门用来存储缓存数据的,不同的服务器缓存都在这个专门的缓存服务器存取。

这里我们介绍mybatis与redis的整合。

mybatis提供了一个eache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。

解决Mybatis自带的二级缓存无法实现分布式缓存的问题,我们使用redis分布式缓存,

mybatis提供了一个针对cache接口的redis实现类,该类存在mybatis-redis包中

具体实现步骤

  1. pom文件
<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-redis</artifactId>
    <version>1.0.0-beta2</version>
</dependency>
  1. 配置文件

Mapper.xml

<cache type="org.mybatis.caches.redis.RedisCache" />

注解

@CacheNamespace(implementation = RedisCache.class)
public interface UserMapper {
  1. redis.properties
redis.host=localhost
redis.port=6379
redis.connectionTimeout=5000
redis.password=
redis.database=0
  1. 测试

直接执行之前的二级缓存测试方法,日志效果是相同的(不要忘了打开redis)

@Test
public void secondLevelCache(){
    SqlSession sqlSession = sqlSessionFactory.openSession();
    SqlSession sqlSession1 = sqlSessionFactory.openSession();
    SqlSession sqlSession2 = sqlSessionFactory.openSession();

    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
    UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);

    User user = userMapper.findUserById(1);
    sqlSession.close();//清空一级缓存
    User user1 = userMapper1.findUserById(1);

    User user2 =new User();
    user2.setId(1);
    user2.setUsername("moyifeng1");
    userMapper2.updateUser(user2);
    sqlSession2.commit();

    User user11 = userMapper1.findUserById(1);
    System.out.println(user==user1);
}

5.redisCache源码分析

  1. RedisCache和普遍实现Mybatis缓存方案大同小异,无非是实现Cache接口并使用jedis操作缓存
  2. RedisCache在mybatis启动的时候,由MyBatis的CacheBuilder创建,创建的方式很简单,就是调用 RedisCache的带有String参数的构造方法,即RedisCache(String id);而在RedisCache的构造方法中, 调用了 RedisConfigu rationBuilder(读取配置文件信息)来创建 RedisConfig 对象,并使用 RedisConfig 来创建JedisPool(Jedis池)。
  3. 另外两个重要的方法就是putObject和getObject,可以知道其就是使用的Redis的Hash来存储的数据。

在这里插入图片描述

八、Mybatis插件

posted @ 2020-11-16 00:59  莫逸风  阅读(104)  评论(0编辑  收藏  举报