目录
(2)自动创建文件、自动设置好代码(能够运行基本增删改查操作,但是除了没有toSping)
4、缓存
MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。 为了使它更加强大而且易于配置,我们对 MyBatis 3 中的缓存实现进行了许多改进。
默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:
当添加上该标签之后,会有如下效果:
- 映射语句文件中的所有 select 语句的结果将会被缓存。
- 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
- 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
- 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
- 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
- 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
在进行配置的时候还会分为一级缓存和二级缓存:
一级缓存:线程级别的缓存,是本地缓存,sqlSession级别的缓存
二级缓存:全局范围的缓存,不止局限于当前会话
mybatis中的缓存机制:
如果没有缓存,那么每次查询的时候都需要从数据库中加载数据,这回造成io的性能问题,所以,在很多情况下
如果连续执行两条相同的sql语句,可以直接从缓存中获取,如果获取不到,那么再去查询数据库,这意味着查询完成的结果需要放到缓存中。
缓存分类:
1、一级缓存:表示sqlSession线程级别的缓存,每次查询的时候会开启一个会话,此会话相当于一次连接,关闭之后自动失效
2、二级缓存:全局范围内的缓存,sqlSession线程关闭之后才会生效
3、第三方缓存:继承第三方的组件,来充当缓存的作用
1、一级缓存:
一级缓存:表示将数据存储在sqlsession线程中,关闭之后自动失效,
默认情况下是开启的
在同一个会话之内,如果执行了多个相同的sql语句,那么除了第一个之外,所有的数据都是从缓存中进行查询的
MyTest.java
@Test
public void test07() throws IOException {
//获取与数据库相关的会话
SqlSession sqlSession线程 = sqlSessionFactory.openSession();
//获取对应的映射接口对象
EmpDao mapper映射 = sqlSession.getMapper(EmpDao.class);
Emp emp = mapper.selectEmpByEmpno(7369);
System.out.println(emp);
sqlSession.close();
}
MyTest.java
@Test
public void test07() throws IOException {
//获取与数据库相关的会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取对应的映射接口对象
EmpDao mapper = sqlSession.getMapper(EmpDao.class);
Emp emp = mapper.selectEmpByEmpno(7369);
System.out.println(emp);
================================== 添加 =======================================
Emp emp2 = mapper2.selectEmpByEmpno(7369);
System.out.println(emp2);
===============================================================================
sqlSession.close();
}
在某些情况下,一级缓存可能会失效?
1、
在同一个方法中,可能会开启多个会话,那么会造成缓存失效。此时需要注意,会话跟方法没有关系,不是一个方法就只能由一个会话,所以严格记住,缓存的数据是保存在sqlsession线程中的
MyTest.java
@Test
public void test07() throws IOException {
//获取与数据库相关的会话
SqlSession sqlSession线程 = sqlSessionFactory.openSession();
//获取对应的映射接口对象
EmpDao mapper映射 = sqlSession.getMapper(EmpDao.class);
Emp emp = mapper.selectEmpByEmpno(7369);
System.out.println(emp);
================================== 添加 =======================================
SqlSession sqlSession2 = sqlSessionFactory.openSession();
EmpDao mapper2 = sqlSession2.getMapper(EmpDao.class);
===============================================================================
Emp emp2 = mapper2.selectEmpByEmpno(7369);
System.out.println(emp2);
sqlSession.close();
sqlSession2.close();
}
2、
当传递对象的时候,如果对象中的属性值不一致,也不会走缓存
MyTest.java
Emp emp = new EmpDao();
@Test
public void test08() throws IOException {
//获取与数据库相关的会话
SqlSession sqlSession线程 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
//获取对应的映射接口对象
EmpDao mapper映射 = sqlSession.getMapper(EmpDao.class);
emp.setEmpno (7369);
Emp emp2 = mapper.selectEmpCondition(emp);
System.out.println(emp2);
emp.setEmpno (7340);
Emp emp3 = mapper.selectEmpCondition(emp);
System.out.println(emp3);
sqlSession.close();
}
3、
在多次查询过程中,如果修改了数据,那么缓存也会失效
EmpDao.java
public interface EmpDao {
public Emp selectEmpByEmpno(Integer empno);
public Emp selectEmpByStep(Integer empno);
public Emp selectEmpByStep2(Integer deptno);
public Emp selectEmpByCondition(Emp emp);
public List<Emp> selectEmpByDeptnos(@Param("deptnos") List<Integer> deptnos);
================================== 添加 =======================================
public Integer update(Emp emp);
===============================================================================
}
EmpDao.xml
<update id="update更新">
update emp set ename=#{ename} where empno = #{empno}
</update>
MyTest.java
@Test
public void test08() throws IOException {
//获取与数据库相关的会话
SqlSession sqlSession线程 = sqlSessionFactory.openSession();
//获取对应的映射接口对象
EmpDao mapper映射 = sqlSession.getMapper(EmpDao.class);
Emp emp = mapper.selectEmpByEmpno(7369);
System.out.println(emp);
System.out.println("==================");
emp.setEname("Teacher教师");
Integer update更新 = mapper.update(emp);
System.out.println(update);
System.out.println("==================");
emp = mapper.selectEmpByEmpno(7369);
System.out.println(emp);
sqlSession.close();
}
//输出共三个
第一查询,第二更新,第三没查询,而是直接输出缓存的数据
4、如果在一个会话过程中,过程中手动清空了缓存,那么缓存也会失效