配置Mybatis二级缓存为Redis来实现内容缓存

为了使用缓存功能,要大量修改Service实现类,增加处理缓存的业务逻辑。有没有一个更好的办法实现呢,不用每次都修改Service具体实现类?

答案是有,我们分析一下我们的架构体系,我们除了可以在Service层做处理意外,也可以考虑在DAO层做处理,但是DAO层我们只是定义了相关接口,具体的数据增删改查都是动态代理在Mybatis层实现的,我们有没有一个办法能在Mybatis层来处理一下实现缓存功能?

答案是有办法,还记得在第四阶段我们学习Mybatis的时候涉及到一个缓存的概念,当时和大家讲过一级缓存和二级缓存

Mybatis二级缓存原理

Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置启动二级缓存。

在同一个namespace下的mapper文件中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操作,则二级缓存清空。

 

二级缓存是mapper级别的。Mybatis默认是没有开启二级缓存。

 

第一次调用mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内。

第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对应的二级缓存内取结果。

如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作。此时会清空该namespace下的二级缓存。

 

代码实例:

 1.导包

2.Mybtais_con.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>

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

    <settings>

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

    </settings>

    <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/test"/>

                <property name="username" value="root"/>

                <property name="password" value="123456"/>

            </dataSource>

        </environment>

    </environments>

    <mappers>

        <mapper resource="UserMapper.xml"/>

    </mappers>

</configuration>

3.mapper文件

<?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.ujiuye.mapper.UserDao">

    <!--eviction="LRU"  redis的内存管理策略-->

    <cache eviction="LRU" type="com.ujiuye.util.RedisCache"/>

 

    <select id="getAll" resultType="com.ujiuye.bean.UserInfo" useCache="true">

        select *from userinfo

    </select>

 

    <update id="update"  parameterType="com.ujiuye.bean.UserInfo">

        update  userinfo set username=#{username},password=#{password} where uid=#{uid}

    </update>

 

    <delete id="del">

        delete  from userinfo where uid=#{0}

    </delete>

 

    <insert id="add" parameterType="com.ujiuye.bean.UserInfo">

        insert into userinfo values (null ,#{username},#{password},#{birthday})

    </insert>

</mapper>

 

4.自定义缓存

public class RedisCache implements Cache {

    private final String id;

    private Jedis jedis;

    public RedisCache(final String id){

        this.id=id;

        System.out.println(">>>>>>>>>id==="+id);

        ApplicationContext context=new ClassPathXmlApplicationContext("bean_core.xml");

        JedisPool jedisPool = context.getBean(JedisPool.class);

        jedis=jedisPool.getResource();

    }

 

    @Override

    public String getId() {

        return this.id;

    }

 

    @Override

    public void putObject(Object key, Object value) {

        jedis.set(key.toString().getBytes(),SerializeUtil.serialize(value));

        System.out.println("===putObject==="+key+"====value="+value);

        jedis.close();

    }

 

    @Override

    public Object getObject(Object key) {

        byte[] bytes = jedis.get(key.toString().getBytes());

        Object value = SerializeUtil.deserialize(bytes);

        System.out.println("===getObject==="+key+"====values=="+value);

        jedis.close();

        return value;

    }

 

    @Override

    public Object removeObject(Object key) {

        //让有效期变成0  ,就自动失效,相当于删除

        Object expire = jedis.expire(key.toString().getBytes(), 0);

        System.out.println("===removeObject=="+expire);

        jedis.close();

        return expire;

    }

 

    @Override

    public void clear() {

        //清空

        jedis.flushDB();

        jedis.close();

    }

 

    @Override

    public int getSize() {

        long size = jedis.dbSize();

        return Integer.parseInt(size+"");

    }

 

    @Override

    public ReadWriteLock getReadWriteLock() {

        return new ReentrantReadWriteLock();

    }

}

5.测试:

@Test

    public void test() throws IOException {

        //1.读取全局配置

        InputStream is= Resources.getResourceAsStream("mybatis_conf.xml");

 

        SqlSessionFactory ssf=new SqlSessionFactoryBuilder().build(is);

 

        SqlSession session=ssf.openSession();

   //执行查询

        UserDao mapper = session.getMapper(UserDao.class);

        List<UserInfo> list = mapper.getAll();

       // System.out.println(list);

 

       //执行更新时,缓存自动删除

        UserInfo u=new UserInfo();

        u.setUsername("admin");

        u.setPassword("123");

        u.setBirthday("2018-2-10 23:12:2");

        mapper.add(u);

        session.commit();

        //不关闭,不会保存缓存

        session.close();

 

    }

第一次 将结果存入缓存中

第二次 不再查询,直接从缓存中读取

 

 

原文地址:https://www.cnblogs.com/masterhxh/p/13044835.html