zoukankan      html  css  js  c++  java
  • 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相关概念.assetsimage-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相关概念.assetsimage-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相关概念.assetsimage-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插件

  • 相关阅读:
    Vue单页面应用
    MVVM模式理解
    Ajax原生四大步骤
    Vue 全家桶介绍
    原生js的dom操作
    vs2015+opencv3.3.1+ maxflow-v3.01 c++实现Yuri Boykov 的Interactive Graph Cuts
    c++迭代递归实现汉诺塔(5种迭代方法满足你)
    opencv3.3.1+vs2015+c++实现直接在图像上画掩码,保存掩码图片
    声明函数指针、回调函数、函数对象------c++程序设计基础、编程抽象与算法策略
    C++/C语言的标准库函数与运算符的区别new/delete malloc/free
  • 原文地址:https://www.cnblogs.com/zhangguangxiang/p/14232485.html
Copyright © 2011-2022 走看看