缓存_构造方法
Java 从 0 到架构师目录:【Java从0到架构师】学习记录
Gitee 代码:mybatis_缓存
缓存
一级缓存 - SqlSession
一级缓存默认开启,缓存内容存放到了 SqlSession 对象中
- 同一个 SqlSession 的 select 共享缓存
- 所以当关闭 SqlSession 时,缓存也就失效了
- 执行 insert、update、delete、commit 等方法时,会自动清理一级缓存
- 由于在很多时候,每次查询用的都是不同的 SqlSession,所以一级缓存的命中率并不高
二级缓存
为了提高缓存的命中率,可以考虑开启 MyBatis 二级缓存,它是 namespace (mapper) 级别的缓存
- 同一个 namespace 下的 select 共享缓存
- 默认情况,namespace 下 update,insert,delete 执行成功时,会自动清理二级缓存
- 当调用 SqlSession 的 close 方法时,会将查询结果放进二级缓存
开启二级缓存
注意区分二级缓存与延迟加载:
- 延迟加载可以全局配置,在 mapper 中覆盖全局的配置
- 二级缓存必须配置全局开始,在 mapper 中再配置是否使用
在 mybatis-config.xml 中配置:
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
在映射文件的 mapper 中添加 cache 标签,默认会缓存映射文件中的所有 select 的结果
<!-- readonly 默认是 false -->
<cache />
<!-- <cache readOnly="false"/> -->
cache 标签的常用属性有:
size
:缓存多少个存储结果(单个对象或一个列表)的引用,默认值是 1024一个 List 里如果装了多个对象,只算作一个引用
eviction
:当缓存数量超过 size 时的清除策略
可选值有 LRU(默认值)、FIFO、SOFT、WEAKflushInterval
:每隔多少毫秒清除一次缓存,默认不会定时清除缓存readonly
:true 代表缓存的是对原对象的引用,false 代表缓存的是原对象序列化后的拷贝对象
所以 false 时要求实现 Serializable 接口;默认值是 false
readonly 为 false 时,在
sqlSession.commit()
时才会将数据放入二级缓存,放入二级缓存之前修改对象的值,和放入二级缓存之后,再去修改对象的值效果是不同的。
useCache - 是否开启二级缓存
可以通过设置 useCache 属性来决定某个 select 是否需要开启二级缓存:
<select id="get"
useCache="false"
parameterType="int"
resultType="com.mj.bean.Skill">
SELECT * FROM skill WHERE id = #{id}
</SELECT>
flushCache - 是否需要清楚缓存
可以通过设置 flushCache 属性来决定某个操作之后,是否需要清除缓存:
<insert id="save"
flushCache="false"
parameterType="com.mj.bean.Skill">
INSERT INTO skill(name, level) VALUES (#{name}, #{level})
</insert>
指定构造方法
XML 中指定构造方法
构造方法的参数顺序与 XML 中可以对应上:
public class Student {
private Integer id;
private String name;
public Student() {}
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
}
<resultMap id="rm" type="com.mj.bean.Student">
<constructor>
<idArg column="id" javaType="int"/>
<arg column="name" javaType="String"/>
</constructor>
</resultMap>
<select id="get" parameterType="int" resultMap="rm">
SELECT * FROM student WHERE id = #{id}
</select>
也可以通过 @Param
指定构造方法的参数名:
public class Student {
private Integer id;
private String name;
public Student() {}
public Student(@Param("id") Integer id,
@Param("name") String name) {
this.id = id;
this.name = name;
}
}
<resultMap id="rm" type="com.mj.bean.Student">
<constructor>
<idArg column="id" javaType="int"/>
<arg column="name" javaType="String"/>
</constructor>
</resultMap>
<select id="get" parameterType="int" resultMap="rm">
SELECT * FROM student WHERE id = #{id}
</select>
注解指定构造方法
public class Student {
private Integer id;
private String name;
public Student() {}
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
}
@Select("SELECT * FROM student WHERE id = #{id}")
@ConstructorArgs({
@Arg(column = "id", javaType = Integer.class, id = true),
@Arg(column = "name", javaType = String.class)
})
Student get(Integer id);