04-Hibernate的缓存和事务
-
Hibernate进阶: 一级缓存
缓存是什么: 提高效率,hibernate中的一级缓存也是为了操作数据库的效率。是从取的角度来提高效率
提高效率的手段1: 提高查询效率
提高效率的手段2:减少不必要的修改语句发送
//测试一级缓存 public class Demo { @Test //证明一级缓存的存在 public void fun1(){ //1、获得Session Session session = HibernateUtils.openSession(); //2、控制事务 Transaction tx = session.beginTransaction(); //3、执行操作 //当有多次执行取操作事,第一次就将取出来的对象放在hibernate缓存中,后面再 //取的时候,先去一级缓存中查找是否存在,存在就直接从缓存中拿,不存在再取数据库中取 Customer c1 = session.get(Customer.class, 1l); Customer c2 = session.get(Customer.class, 1l); Customer c3 = session.get(Customer.class, 1l); Customer c4 = session.get(Customer.class, 1l); Customer c5 = session.get(Customer.class, 1l); System.out.println(c3 == c5); //true,理由是同一个对象 //4、提交事务、关闭事务 tx.commit(); session.close();//游离状态|托管状态, 有id,没有关联 } @Test //一级缓存中修改参数 public void fun2(){ //1、获得Session Session session = HibernateUtils.openSession(); //2、控制事务 Transaction tx = session.beginTransaction(); //3、执行操作 Customer c1= session.get(Customer.class, 1L); //如果是多次修改时,则在缓存中修改前面的值,最后一次的值才会执行到数据库中 c1.setCust_name("清子"); c1.setCust_name("哈哈哈"); //4、提交事务、关闭事务 tx.commit(); session.close();//游离状态|托管状态, 有id,没有关联 } @Test //持久化状态对象其实就是放入session缓存中的对象 public void fun3(){ //1、获得Session Session session = HibernateUtils.openSession(); //2、控制事务 Transaction tx = session.beginTransaction(); //3、执行操作 Customer c1 = new Customer(); c1.setCust_id(1l); session.update(c1); Customer c2 = session.get(Customer.class, 1l); c1.setCust_name("暖男"); c1.setCust_name("哈哈哈哈"); //4、提交事务、关闭事务 tx.commit(); session.close();//游离状态|托管状态, 有id,没有关联 } }
-
hibernate的事务
- 事务特性
- 原子性
- 一致性
- 隔离性
- 持久性
- 事务并发问题
- 脏读
- 不可重复读
- 幻读|虚读
- 事务的隔离级别
- 读未提交
- 读已提交
- 可重复读 (mysql)默认的隔离级别3
- 串行化
- 事务特性
-
补充知识点
- 知识点1: 如何在Hibernate中指定数据库的隔离级别
<!--指定hibernate操作数据库时的隔离级别 ##specify a jdbc isolation level # hibernate.connection.isolation 1|2|4|8 0001 1 读未提交 0010 2 读已提交 0100 4 可重复读 1000 8 串行化 --> <property name="hibernate.connection.isolation">4</property>
-
知识点2: 在项目中如何管理事务
业务开始之前打开事务,业务执行之后提交事务,执行过程中出现异常,回滚事务
在Dao曾操作数据库需要用到session对象,在sevice控制事务也是需要使用session对象完成
我们要确保dao曾service层使用的是同一个session对象
我们开发人员只需要调用sf.getCurrentSession()方法即可获取与当前线程绑定的session对象
注意1 : 调用getCurrentSession()方法必须配置主配置文件中的一段配置
<!-- 指定session与当前线程绑定 --> <property name="hibernate.current_session_context_class">thread</property>
注意2:通过getCurrentSession方法获得的session对象,当事务提交时,session会自动关闭。切记不要手动调用close关闭。
crm项目的事务改造(课后自己手动改造)
public class Demo { @Test //返回了同一个与线程绑定的session public void fun1(){ Session session1 = HibernateUtils.getCurrentSession(); Session session2 = HibernateUtils.getCurrentSession(); System.out.println(session1 == session2); //true } @Test //返回了不同的session public void fun2(){ Session session1 = HibernateUtils.openSession(); Session session2 = HibernateUtils.getCurrentSession(); System.out.println(session1 == session2); //false } }