文章目录
一、Mybatis的二级缓存
二级缓存是SqlSessionFactory级别的缓存,同一个SqlSessionFactory产生的SqlSession都共享一个二级缓存,二级缓存中存储的是数据,当命中二级缓存时,通过存储的数据构造对象返回。查询数据的时候,查询的流程是二级缓存>一级缓存>数据库。
二、二级缓存的使用原则
(1)只能在一个命名空间下使用二级缓存
由于二级缓存中的数据是基于namespace的,即不同namespace中的数据互不干扰。在多个namespace中若均存在对同一个表的操作,那么这多个namespace中的数据可能就会出现不一致现象。
(2)在单表上使用二级缓存
如果一个表与其它表有关联关系,那么就有可能存在多个namespace对同一数据的操作。而不同namespace中的数据互不干扰,所以就有可能出现多个namespace中的数据不一致现象。
(3)查询多于修改时使用二级缓存
在查询操作远远多于增删改操作的情况下可以使用二级缓存。因为任何增删改操作都将刷新二级缓存,对二级缓存的频繁刷新将降低系统性能。
三、二级缓存的使用步骤
1.配置Mybatis框架支持二级缓存
Mybatis3以后已经不需要下面的语句,自身已经支持了二级缓存。
<settings>
<!-- 设置Mybatis支持二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
全局配置文件如下:
<?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>
<properties resource="db.properties"></properties>
<settings>
<!-- 设置延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 设置支持二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<mappers>
<!-- 使用接口的全限定名,接口名必须和sql配置文件同名且同级目录 -->
<package name="com.gql.mapper"/>
</mappers>
</configuration>
2. 配置dao层xml支持二级缓存
在dao层的xml配置中加入下面的标签,就代表dao层也支持二级缓存了。
<cache/>
dao层xml配置如下:
<?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.gql.mapper.UserMapper">
<!-- dao层配置开启二级缓存 -->
<cache/>
<select id="getUserById" parameterType="java.lang.Integer" resultType="com.gql.pojo.User">
SELECT id,username,sex,address,birthday FROM user WHERE id = #{id};
</select>
<update id="updateUser" parameterType="com.gql.pojo.User">
UPDATE user SET
username=#{username},
sex=#{sex},
address=#{address},
birthday=#{birthday}
WHERE id =#{id};
</update>
</mapper>
三、测试二级缓存
全局配合和dao层配置在上面已经给出。
1.User对象的pojo
package com.gql.pojo;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 类说明:
* User_JavaBean
* @guoqianliang1998.
*/
public class User implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String username;
private String sex;
private String address;
private Date birthday;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
2.dao层接口
package com.gql.mapper;
import java.util.List;
import com.gql.pojo.User;
/**
* 类说明:
* 接口
* @guoqianliang1998.
*/
public interface UserMapper {
User getUserById(int id);
}
3.测试二级缓存
package com.gql.mapper;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import com.gql.pojo.User;
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException{
String resource = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
}
@Test
public void testCache2(){
//1.使用session1进行查询
SqlSession session1 = sqlSessionFactory.openSession();
UserMapper userMapper1 = session1.getMapper(UserMapper.class);
User user1 = userMapper1.getUserById(1);
System.out.println(user1.getUsername());
//2.关闭sessin1
session1.close();
//3.使用session2进行查询
SqlSession session2 = sqlSessionFactory.openSession();
UserMapper userMapper2 = session2.getMapper(UserMapper.class);
User user2 = userMapper2.getUserById(1);
System.out.println(user1.getUsername());
}
}
在debug模式下单步调试上述代码:
①session1的代理对象调用查询方法时,向数据库发送了sql命令。
②关闭session1,使用session2的代理对仍进行查询时,并没有执行ssql命令。
这说明,同一个SqlSessionFactory产生的SqlSession共享同一个二级缓存,二级缓存测试成功。