mybatis中的缓存问题解析
关于mybatis基础我们前面几篇博客已经介绍了很多了,今天我们来说一个简单的问题,那就是mybatis中的缓存问题。mybatis本身对缓存提供了支持,但是如果我们没有进行任何配置,那么默认情况下系统只开启了一级缓存,一级缓存就是同一个sqlsession执行的相同查询是会进行缓存的,ok,那么今天我们就来看看这些缓存,并简单验证下。
系统默认开启了一级缓存
这个缓存系统默认情况下是开启的,当我们获取到一个sqlsession对象之后,如果调用sqlsession中的同一个方法查询同一条数据,那么第二次查询将不会去数据库中查询,因为第一次查询有缓存,直接调用缓存数据即可,除非缓存超时或者我们明确声明数据要刷新,否则都是直接调用缓存数据。ok,我们来看一个简单的案例。
查询代码如下:
sqlsession sqlsession = null; try { sqlsession = dbutils.opensqlsession(); usermapper mapper = sqlsession.getmapper(usermapper.class); //查询同一条数据时会缓存 user user = mapper.getuser(1l); user user2 = mapper.getuser(1l); system.out.println(user.tostring()); system.out.println(user2.tostring()); sqlsession.commit(); } catch (exception e) { system.err.println(e.getmessage()); sqlsession.rollback(); } finally { if (sqlsession != null) { sqlsession.close(); } }
我们来看看日志:
小伙伴们看到,我这里执行了两次查询,但实际上只执行了一次sql语句。
自己配置二级缓存
上面的缓存是由系统默认配置的,这个有一定的局限性,就是只能在同一个sqlsession中有效,脱离了同一个sqlsession就没法使用这个缓存了,有的时候我们可能希望能够跨sqlsession进行数据缓存。那么这个时候需要我们进行手动开启二级缓存。
二级缓存的开启方式其实很简单,只需要我们在usermapper.xml中配置<cache/>节点即可。如下:
<?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="org.sang.db.usermapper"> <cache/> <select id="getuser" resulttype="org.sang.bean.user" parametertype="long"> select * from user where id = #{id} </select> <insert id="insertuser" parametertype="org.sang.bean.user"> insert into user(username,password,address) values (#{username},#{password},#{address}) </insert> <delete id="deleteuser" parametertype="long"> delete from user where id=#{id} </delete> <select id="getall" resulttype="u"> select * from user </select> </mapper>
这样简单配置之后,二级缓存就算开启了,这样的配置中,许多东西都是默认的,比如所有的select语句都会被缓存,所有的delete、insert和update则都会将缓存刷新,还比如缓存将使用lru算法进行内存回收等。那么这些东西如果需要配置的话,我们可以按如下方式进行配置:
<cache eviction="lru" flushinterval="20000" size="1024" readonly="true"/>,这里的eviction表示缓存策略,除了lru之外还有先进先出(fifo)、软引用(soft)、弱引用(weak)等,flushinterval则表示刷新时间,表示缓存的对象个数,readonly为true则表示缓存只可以读取不可以修改。
ok,做了如上配置之后还不够,开启二级缓存还要求我们的实体类可以序列化,实现serializable接口即可,如下:
public class user implements serializable{ private long id; private string username; private string password; private string address; ... }
如此之后,我们的二级缓存就算成功开启了,ok,我么来测试下:
sqlsession sqlsession = null; sqlsession sqlsession2 = null; try { sqlsession = dbutils.opensqlsession(); usermapper mapper = sqlsession.getmapper(usermapper.class); user user = mapper.getuser(1l); system.out.println(user.tostring()); sqlsession.commit(); sqlsession2 = dbutils.opensqlsession(); usermapper mapper2 = sqlsession2.getmapper(usermapper.class); user user2 = mapper2.getuser(1l); system.out.println(user2.tostring()); sqlsession2.commit(); } catch (exception e) { system.err.println(e.getmessage()); sqlsession.rollback(); sqlsession2.rollback(); } finally { if (sqlsession != null) { sqlsession.close(); } if (sqlsession2 != null) { sqlsession2.close(); } }
打印日志如下:
ok,小伙伴们看到sql语句实际上只执行了一次。
ok,以上就是对mybatis中缓存的一个简单介绍。
本文案例下载: 本文案例github地址https://github.com/lenve/javaeetest/tree/master/test27-mybatis8
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: VB.NET拷贝整个目录下所有子目录及文件的实例代码
下一篇: android搜索框上下滑动变色效果
推荐阅读
-
mybatis中的缓存问题解析
-
深入解析Android系统中应用程序前后台切换的实现要点
-
Android Material设计中列表和卡片的创建方法解析
-
Android中Glide加载库的图片缓存配置究极指南
-
Android中利用NetworkInfo判断网络状态时出现空指针(NullPointerException)问题的解决方法
-
MyBatis批量插入数据到Oracle数据库中的两种方式(实例代码)
-
全面解析Android中对EditText输入实现监听的方法
-
PHP 中 DOMDocument保存xml时中文出现乱码问题的解决方案
-
java继承中的构造方法实例解析
-
从源码解析Android中View的容器ViewGroup