“缓存并不是基于行的”的意思就是,mybatis缓存的粒度是全部查询结果,而不是查询结果的每行,这也就意味着每次查询,就只有一份缓存,而不是有几行就有几分缓存。
这点和hibernate很不同,hibernate的缓存是基于每个对象的,即查询出来的有几个对象,那就有几份缓存。
mybatis无法像hibernate给每个对象做缓存,主要原因是mybatis非常自由,能够配置任意的返回结果类型,这也就是说返回的结果并不一定都有主键,如此一来也就没有办法标识某一行数据和哪个返回结果对应,而hibernate是强制你所映射的每个类都要有主键的。
参考文档: http://www.mybatis.org/mybatis-3/sqlmap-xml.html#cache
“缓存默认没有失效时间”的意思是如果我们直接在数据库里修改数据,那么每次用mybatis查询的时候,使用的还是上一次的缓存结果,且这份缓存一直有效,除非我们通过mapper调用了update、delete、insert方法,这些方法会使缓存失效。解决办法很简单,就是在使用 <cache />
的时候一定要写上 flushInterval
属性。
参考文档: http://www.mybatis.org/mybatis-3/sqlmap-xml.html#cache
Partial Auto-mapping的意思是你对ResultMap只提供了部分字段的配置而不是全部字段,但是如果你的这个ResultMap没有设置ID,也就是主键,那么mybatis将会根据你提供的这一部分字段配置来判断两行数据是否重复,并且会将重复的去掉。
实际上关于id的作用在官方文档中很隐晦的提到过了:见 http://www.mybatis.org/mybatis-3/sqlmap-xml.html#Result_Maps 的id & result部分。
比如下面这个配置启用了 autoMapping
,且部分配置了property的映射。在这种情况下,如果查询出两条记录了,而这两条记录的 task_key
的值是一样的时候,mybatis就会认为是同一条,最终返回给你一个 AuditLog
。
<resultMap id="AuditLog" type="AuditLog" autoMapping="true"> <result column="task_key" property="taskKey"/> </resultMap>
解决办法有两个:
不配置property的映射:
<resultMap id="AuditLog" type="AuditLog" autoMapping="true"> </resultMap>
不使用automapping:
<resultMap id="AuditLog" type="AuditLog"> <result column="task_key" property="taskKey"/> <result column="result" property="result"/> <result column="when" property="when"/> <result column="name_zh" property="nameZh"/> <result column="name_en" property="nameEn"/> <result column="remark" property="remark"/> </resultMap>
参考文档: http://www.mybatis.org/mybatis-3/sqlmap-xml.html#Auto-mapping
在使用mybatis懒加载特性的时候有一点需要注意,就是要把 aggressiveFetch
设置为 false
。
根据官方文档,当设置为true的时候,如果你get了懒加载属性,那么其他懒加载属性也会一并加载。
但实际情况时,当设置了true的时候,如果你get了 任一 属性,那么 所有 懒加载属性也会一并加载。