MyBatis事务和缓存机制
事务是由一步或者几步数据库操作序列组成逻辑执行单元
,这系列要么全部执行,要不全部放弃执行。程序和事务是两个不同的概念。一般程序中可能包含多个事务。
事务具有四个特性
原子性(Atomicity):事务是应用中的最小执行单位,具有不可再分的特征
一致性(Consistency):事务执行的结果,必须是数据库从一个一致性状态,变成到另一个一致性状态,当数据库只包含事务成功提交的结果时,数据库处于一致性状态。
隔离性(Isolation):各个事务的执行互不干扰。并发执行的事务之间不能看到对方的中间状态,并发执行的事务之间不能互相影响。
持续性(Durability):持续性也称为持久性,事务一旦提交,对数据库所做的任何改变,都要记录到永久存储器中,通常保存进入物理数据库。
MyBatis的事务主要分为两种形式:
JdbcTransaction: 直接使用JDBC的提交和回滚事务管理机制
ManagedTransaction:让容器来管理事务Transaction的整个生命周期
MyBatis的缓存机制
在实际开发中,通常对数据库查询的性能要求很高,MyBatis提供了查询缓存来缓存数据,从而达到提高查询的效率。
一级缓存:SqlSessioin级别的缓存
当同一个SqlSession中执行两次相同的Sql语句时,当第一次执行完毕会将数据库中查询的数据写到缓存(内存)中,第二次查询时,会从缓存中获取数据,不去底层进行数据库查询,从而提高了查询效率。
MyBatis默认开启一级缓存,不需要进行任何配置。
@Test
public void testCache(){
SqlSession session=ssf.openSession();
Father father=session.selectOne("com.ryh.mapper.FatherMapper.selectByPrimaryKey",3);
System.out.println(father.getFname());
// // 再次查询id为1811的User对象,因为是同一个SqlSession,所以会从之前的一级缓存中查找数据
Father father2=session.selectOne("com.ryh.mapper.FatherMapper.selectByPrimaryKey",3);
System.out.println(father2.getFname());
session.close();
}
实际上一级缓存就是之前第一遍执行硬盘,第二次不再执行硬盘而是用之前查过的数据直接输出,以此提高效率。
@Test
public void testCache2(){
SqlSession session=ssf.openSession();
Father father=session.selectOne("com.ryh.mapper.FatherMapper.selectByPrimaryKey",3);
System.out.println(father.getFname());
session.delete("com.ryh.mapper.FatherMapper.deleteByPrimaryKey",2);
session.commit();
// 再次查询id为1的User对象,因为DML操作会清空SqlSession缓存,所以会再次执行select语句
Father father2=session.selectOne("com.ryh.mapper.FatherMapper.selectByPrimaryKey",3);
System.out.println(father2.getFname());
session.close();
}
注意:如果之前执行其他操作需要重新执行第二次。
@Test
public void testCache3(){
SqlSession session=ssf.openSession();
Father father=session.selectOne("com.ryh.mapper.FatherMapper.selectByPrimaryKey",3);
System.out.println(father.getFname());
session.close();
SqlSession session1=ssf.openSession();
// 再次查询id为1的User对象,因为session是新的session。因此清空SqlSession缓存,所以会再次执行select语句
Father father1=session1.selectOne("com.ryh.mapper.FatherMapper.selectByPrimaryKey",3);
System.out.println(father1.getFname());
session1.close();
}
再次查询id为1的对象,因为session是新的session,因此清空Sqlsession缓存,所以会再次执行select语句
二级缓存:mapper级别的缓存
其中二级缓存是多个SqlSession共享的,mybatis通过缓存机制减轻数据压力,提高数据库性能
开启二级缓存的步骤
先在mybatis.cfg.xml文档上设置开启二级缓存
<setting name="cacheEnabled" value="true"/>
然后在你需要开启的Mapper上面写(在类的开头部分)
@CacheNamespace(size = 512)
@Test
public void testCache4(){//当关闭一级缓存的时候 我们由于开了二级缓存 因此 关闭session之后 可以取二级缓存中查找
SqlSession session=ssf.openSession();
Father father=session.selectOne("com.ryh.mapper.FatherMapper.selectByPrimaryKey",3);
System.out.println(father.getFname());
session.close();
SqlSession session1=ssf.openSession();
// 再次查询id为1的User对象,因为session是新的session。因此清空SqlSession缓存,所以会再次执行select语句
Father father1=session1.selectOne("com.ryh.mapper.FatherMapper.selectByPrimaryKey",3);
System.out.println(father1.getFname());
session1.close();
}
当我们关闭一级缓存的时候,由于开启了二级缓存,因此关闭session之后可以去二级缓存中查找
所以在执行上面语句的时候由于开启二级缓存,即使开启了两个session也只执行一遍