- 설명 : 지속성 프레임 워크의 대부분과 마찬가지로, MyBatis로는 성능 향상을 위해 전략을 캐싱하여 데이터베이스 쿼리의 수를 줄이기 위해 캐싱 전략을 제공합니다.
캐시
- 의 존재를 증명 캐시
캐시하는 한 SQLSESSION로 더 높이 또는 가까운 SQLSESSION 레벨 캐시, 그것은 존재한다. - 쓰기 사용자 인터페이스 지속성 계층 다오
public interface IUserDao {
/**
* 根据 id 查询
* @param userId
* @return
*/
User findById(Integer userId);
}
- 레이어 매핑 파일 지속성 쓰기 사용자
<?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.itheima.dao.IUserDao">
<!-- 根据 id 查询 -->
<select id="findById" resultType="UsEr" parameterType="int" useCache="true">
select * from user where id = #{uid}
</select>
</mapper>
- 작문 시험 방법
public class UserTest {
private InputStream in ;
private SqlSessionFactory factory;
private SqlSession session;
private IUserDao userDao;
@Test
public void testFindById() {
//6.执行操作
User user = userDao.findById(41);
System.out.println("第一次查询的用户:"+user);
User user2 = userDao.findById(41);
System.out.println("第二次查询用户:"+user2);
System.out.println(user == user2);
}
@Before
//在测试方法执行之前执行
public void init()throws Exception {
//1.读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建构建者对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.创建 SqlSession 工厂对象
factory = builder.build(in);
//4.创建 SqlSession 对象
session = factory.openSession();
//5.创建 Dao 的代理对象
userDao = session.getMapper(IUserDao.class);
}
@After
//在测试方法执行完成之后执行
public void destroy() throws Exception{
//7.释放资源
session.close();
in.close();
}
}
다음과 같이 테스트 결과는 다음과 같습니다
- 우리는이 비록 위의 코드에서 우리는 두 번 쿼리를 볼 수 있지만, 우리의 MyBatis 레벨 캐시 작업 사용할 수있는 데이터베이스 작업의 끝에서만 구현 할 수 있습니다. 버퍼의 존재 레코드 (41)의 ID에서 두 번째 쿼리 결과, 그리고 SQL 문을 데이터베이스 쿼리의 데이터 만 캐시에서 쿼리를 실행하지 않기 때문에.
- 의 캐시 분석
당신의 SQLSESSION을 수정, 추가, 삭제, (커밋 호출 할 때 캐시가 가까운), () 메소드 등 캐시 SQLSESSION 범위, 그것은 캐시를 비우는 것입니다.
- 삭제 캐시 테스트
/**
* 测试一级缓存
*/
@Test
public void testFirstLevelCache(){
User user1 = userDao.findById(41);
System.out.println(user1);
sqlSession.clearCache();//此方法也可以清空缓存
userDao = sqlSession.getMapper(IUserDao.class);
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
/**
* 测试缓存的同步
*/
@Test
public void testClearlCache(){
//1.根据 id 查询用户
User user1 = userDao.findById(41);
System.out.println(user1);
//2.更新用户信息
user1.setUsername("update user clear cache");
user1.setAddress("北京市海淀区");
userDao.updateUser(user1);
//3.再次查询 id 为 41 的用户
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
当执行sqlSession.close()后,再次获取sqlSession并查询id=41的User对象时,又重新执行了sql
语句,从数据库进行了查询操作。
MyBatis로 보조 캐시
보조 캐시 레벨 캐시를 매핑하는 맵퍼는, 복수 SQLSESSION SQL 문은 보조 캐시의 SQLSESSION에서 보조 캐시의 SQLSESSION의 복수를 공유 할 수 있습니다, 같은 매퍼가 매핑 조작합니다.
- 2 차 캐쉬의 구성도
차 캐시의 MyBatis의 제집니다.
sqlSession1는 사용자 정보 쿼리 데이터가 보조 캐시에 저장됩니다 쿼리 사용자 정보를 조회 할 수 있습니다.
동일한 데이터가 실행을 저지 SQL을 매핑 매퍼 SqlSession3을 수행 할 경우, 매퍼 매핑의 2 차 캐시 영역이 삭제됩니다.
캐시에서 직접 촬영 한 데이터가있는 경우 sqlSession2 sqlSession1는 먼저 캐시에 데이터가 있는지 찾을 것 같은 사용자 정보를 조회합니다.
ON과 OFF 차 캐시
- 첫 번째 단계 : SqlMapConfig.xml에서 보조 캐시 파일을 켭니다
<settings>
<!-- 开启二级缓存的支持 -->
<setting name="cacheEnabled" value="true"/>
</settings>
因为 cacheEnabled 取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;
为false 代表不开启二级缓存。
- 단계 : 구성 관련 매퍼 매핑 파일
<cache>标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace值。
<?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.itheima.dao.IUserDao">
<!-- 开启二级缓存的支持 -->
<cache></cache>
</mapper>
- 세 번째 단계 : 위의 문장 구성이 useCache 속성
<!-- 根据 id 查询 -->
<select id="findById" resultType="user" parameterType="int" useCache="true">
select * from user where id = #{uid}
</select>
将 UserDao.xml 映射文件中的<select>标签中设置 useCache=”true”代表当前这个
statement 要使用二级缓存,如果不使用二级缓存可以设置为 false。
注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。
- 차 캐시 테스트
public class SecondLevelCacheTest {
private InputStream in;
private SqlSessionFactory factory; @Before//用于在测试方法执行之前执行
public void init()throws Exception{
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取 SqlSessionFactory
factory = new SqlSessionFactoryBuilder().build(in);
}@After//用于在测试方法执行之后执行
public void destroy()throws Exception{
in.close();
}
/**
* 测试一级缓存
*/
@Test
public void testFirstLevelCache(){
SqlSession sqlSession1 = factory.openSession();
IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);
User user1 = dao1.findById(41);
System.out.println(user1);
sqlSession1.close();//一级缓存消失
SqlSession sqlSession2 = factory.openSession();
IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);
User user2 = dao2.findById(41);
System.out.println(user2);
sqlSession2.close();
System.out.println(user1 == user2);
}
}
위의 테스트 후에, 우리는이 개 질문의 구현, 그리고 첫 번째 쿼리를 수행 한 후, 우리는 두 번째 쿼리를 수행하기 위해 이동하여 첫 번째 레벨 캐시를 폐쇄 발견, 우리는 데이터베이스에 발행 된 어떠한 SQL 문을 발견이 너무 데이터는 단지 우리가 차 캐시를 부르는에서 파생 될 수있다.
- 차 캐시 노트
当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,
这种就可以使用序列化
方式来保存对象。
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
}