`
liyixing1
  • 浏览: 941123 次
  • 性别: Icon_minigender_1
  • 来自: 江西上饶
社区版块
存档分类
最新评论

ibatis缓存

阅读更多
ibatis的session缓存。做了一个测试
<?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.liyixing.ibatis.dao.IAccountDao">
<resultMap type="com.liyixing.ibatis.model.Account" id="account">
<id property="id" column="ID" />
<result property="userName" column="USER_NAME" />
<collection property="messages" javaType="ArrayList"
column="ID" ofType="com.liyixing.ibatis.model.Message" select="getMyMessage">
</collection>
</resultMap>

<select id="getMyMessage" parameterType="_int" resultMap="message">
SELECT
ID,
USER_ID,
MESSAGE,
MESSAGE_TYPE
FROM message
WHERE USER_ID = #{id}
</select>

<select id="getAccount" parameterType="_int" resultMap="account">
SELECT *
FROM account WHERE ID = #{id}
</select>

<select id="getAccountByName" parameterType="string" resultMap="account">
SELECT *
FROM account WHERE USER_NAME = #{userName}
</select>
</mapper>

在没有做和缓存相关的任何配置前
Reader reader = Resources
.getResourceAsReader("com/liyixing/ibatis/data/ibatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
.build(reader);
SqlSession session = factory.openSession();
IAccountDao accountDao = session.getMapper(IAccountDao.class);
Account account0 = accountDao.getAccount(1);
Account account1 = accountDao.getAccount(1);
Account account2 = accountDao.getAccountByName("liyixing");
Account account3 = accountDao.getAccountByName("liyixing");
这里account0,account1,account2,account3 四个对象,在eclipse的debug可以看到对象的唯一标示id



account0,account1通过同一个方法(select id="getAccount")来获取的
发现account0,account1是同一个对象。因此得出默认的ibatis开启了session缓存。
account2与account3相同,但是和account0,account1他两的对象标示不相同。说明默认的ibatis的缓存是针对select id,来处理的。

修改配置
<settings>
<setting name="cacheEnabled" value="false" />
</settings>
结果相同和上面相同。


update对其的影响
Reader reader = Resources
.getResourceAsReader("com/liyixing/ibatis/data/ibatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
.build(reader);
SqlSession session = factory.openSession();
IAccountDao accountDao = session.getMapper(IAccountDao.class);
Account account0 = accountDao.getAccount(1);
Account account1 = accountDao.getAccount(1);
Account account2 = accountDao.getAccountByName("liyixing");
Account account3 = accountDao.getAccountByName("liyixing");
int x = accountDao.updateAccount(1);
Account account5 = accountDao.getAccount(1);
Account account6 = accountDao.getAccountByName("liyixing");
Account account7 = accountDao.getAccountByName("liyi");
这里有一句修改的语句




可以看出来,account5在修改之后,查询的,是一个新的对象,可以得出update是会清理缓存。
Account account6 = accountDao.getAccountByName("liyixing");
Account account7 = accountDao.getAccountByName("liyi");
可以看出update清理的缓存是全局的。那么会不会只是针对对象的主键来清理缓存的呢?
Reader reader = Resources
.getResourceAsReader("com/liyixing/ibatis/data/ibatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
.build(reader);
SqlSession session = factory.openSession();
IAccountDao accountDao = session.getMapper(IAccountDao.class);
Account account0 = accountDao.getAccount(1);
Account account1 = accountDao.getAccount(1);
Account account2 = accountDao.getAccountByName("liyixing");
Account account3 = accountDao.getAccountByName("liyixing");
Account account8 = accountDao.getAccountByName("liyimao");
int x = accountDao.updateAccount(1);
Account account5 = accountDao.getAccount(1);
Account account6 = accountDao.getAccountByName("liyixing");
Account account7 = accountDao.getAccountByName("liyi");
Account account9 = accountDao.getAccountByName("liyimao");
这里的name liyixing和liyimao是两个不同的主键值。
然后修改发现account8,和account9也是不同的对象。因此得出update清理的缓存涉及的范围很广。至于会不会影响到其他对象,比如Message对象呢?
Reader reader = Resources
.getResourceAsReader("com/liyixing/ibatis/data/ibatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
.build(reader);
SqlSession session = factory.openSession();
IAccountDao accountDao = session.getMapper(IAccountDao.class);
IMessageDao messageDao = session.getMapper(IMessageDao.class);
Account account0 = accountDao.getAccount(1);
Account account1 = accountDao.getAccount(1);
Account account2 = accountDao.getAccountByName("liyixing");
Account account3 = accountDao.getAccountByName("liyixing");
Account account8 = accountDao.getAccountByName("liyimao");
Message message0 = messageDao.getMessage(1);
Message message2 = messageDao.getMessage(1);
int x = accountDao.updateAccount(1);
Message message1 = messageDao.getMessage(1);
Account account5 = accountDao.getAccount(1);
Account account6 = accountDao.getAccountByName("liyixing");
Account account7 = accountDao.getAccountByName("liyi");
Account account9 = accountDao.getAccountByName("liyimao");

System.out.println("age:" + account0.getMessages().size());
debug


可以看出来其他对象也影响了。

上面的调试结果,可以从源码中看出来。
但是源码的话看起来可能需要更多的时间。因此做了这个测试。

不同的session中,缓存是不共享的。


二级缓存,在sql映射文件中
<cache/>
语句的效果如下:
 映射语句文件中的所有select语句将会被缓存。
 映射语句文件中的所有insert,update和delete语句会刷新缓存。
 缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回。
 根据时间表(比如no Flush Interval,没有刷新间隔),缓存不会以任何时间顺序来刷新。
 缓存会存储列表集合或对象(无论查询方法返回什么)的1024个引用。
 缓存会被视为是read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。注意这里的readyonly是只只有在读的时候才不会出现线程问题。而写的时候可能会出现线程问题。

<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
创建了一个FIFO缓存,并每隔60秒刷新,存数结果对象或列表的512个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。


可用的收回策略有:
 LRU – 最近最少使用的:移除最长时间不被使用的对象。
 FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
 SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
 WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
默认的是LRU。
flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。
readOnly(只读)属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
readOnly关于这个属性,不是很理解。

使用自定义缓存
<cache type=”com.domain.something.MyCustomCache”/>
type属性指定别的缓存实现。
org.mybatis.cache.Cache实现这个接口。默认的缓存时间,用的是org.apache.ibatis.cache.impl.PerpetualCache
要给缓存传递出了以上的属性之外的其他属性,通过property子元素
<cache readOnly="false">
<property name="" value=""/>
</cache>

针对语句的缓存设置
<select ... flushCache=”false” useCache=”true”/>
<insert ... flushCache=”true”/>
<update ... flushCache=”true”/>
<delete ... flushCache=”true”/>
上面都是默认值

缓存配置共享
<cache-ref namespace=”com.someone.application.data.SomeMapper”/>
比如我在Account.xml配置了缓存
<mapper namespace="com.liyixing.ibatis.dao.IAccountDao">
<cache readOnly="false" />

在Message.xml要应用这个配置
<mapper namespace="com.liyixing.ibatis.dao.IMessageDao">
<cache-ref namespace="com.liyixing.ibatis.dao.IAccountDao"/>
  • 大小: 2.4 KB
  • 大小: 6 KB
  • 大小: 2.8 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics