Hibernate之事务处理
时间:2017-1-24 21:56
——事务
1、什么是事务
事务就是逻辑上的一组操作,要么全都成功,要么全部失败
2、事务的特性
1)原子性
一组事务的操作不可分割。
2)一致性
事务的执行前后,数据完整性要保持一致。
3)隔离性
一个事物在执行的过程中不应该受到其他事务的干扰。
4)持久性
一旦事务结束,数据就永久保存到数据库。
3、安全问题
5大类问题:3类读问题,2类写问题
1)读问题
* 脏读
一个事务读到另一个事务未提交的数据。
* 不可重复读
一个事务读到另一个事务已提交的数据(update),导致查询结果不一致。
* 虚读
一个事务读到另一个事务已提交的数据(insert),导致查询结果不一致。
2)可以通过设置事务的隔离级别来避免三种读问题:
* 未提交读
以上三种读问题都有可能发生。
* 已提交读
可以避免脏读,不能避免不可重复读和虚读。
* 重复读
可以避免脏读和不可重复读,不能避免虚读。
* 串行的
可以避免以上三种读问题。
3)可以通过核心配置文件的配置,来设置事务隔离级别:
例如:hibernate.connection.isolation=4
4)写问题
数据更新丢失问题,当两个事务更新了同一条记录,会导致后提交的事务覆盖前提交的事务。
可以使用悲观锁或乐观锁来解决:
悲观锁:(排它锁)
当前事务会锁定当前记录,其他事务无法访问。
// 使用悲观锁(排它锁)
乐观锁:
会通过一个version字段来判断当前记录是否已经被修改。
* 在实体类中添加private Integer version;字段
* 在映射文件中添加<version name="version" />属性
// 使用乐观锁
Customer customer = (Customer)session.get(Customer.class, 1);
——Session的事务问题
问题:
Session存在于DAO层,而事务通常在Service层开启,如何保证使用的Session属于同一个事务
1、尽管让程序自主管理Session对象的生命周期也是可行的,但在实际Java应用开发中,把管理Session对象的生命周期交给Hibernate管理,可以简化Java应用程序代码和软件架构。
2、Hibernate3本身提供了三种管理Session对象的方法:
1)Session对象的生命周期与本地线程绑定(ThreadLocale)
2)Session对象的生命周期与JTA事务绑定。
3)Hibernate委托程序管理Session对象的生命周期。
3、在Hibernate的配置文件中,hibernate.current_session_context_class属性用于指定Session的管理方式,可选值包括:
1)thread:Session对象的生命周期与本地线程绑定。
2)jta*:Session对象的生命周期与JTA事务绑定。
3)managed:Hibernate委托程序来管理Session对象的生命周期。
4、Session对象的生命周期与本地线程绑定
1)如果把Hibernate配置文件的hibernate.current_session_context_class属性设置为thread,Hibernate就会按照本地线程绑定的方式来管理Session。
2)Hibernate按照以下规则把Session与本地线程绑定:
* 当一个线程(ThreadA)第一次调用SessionFactory对象的getCurrentSession()方法时,该方法会创建一个新的Session(SessionA)对象,把该对象与ThreadA绑定并将SessionA对象返回。
* 当ThreadA再次调用SessionFactory对象的getCurrentSession()方法时,该方法将返回SessionA对象。
* 当ThreadA提交SessionA对象相关事务的时候,Hibernate会自动清理SessionA对象的缓存,然后提交事务,关闭SessionA对象,当ThreadA撤销SessionA对象关联事务的时候,也会自动关闭SessionA对象。
* 若ThreadA再次调用SessionFactory对象的getCurrentSession()方法时,该方法又会创建一个新的Session(SessionB)对象,把该对象与ThreadB绑定,并返回SessionB。
5、使用方法
1)在hibernate.cfg.xml文件中配置:
<property name="hibernate.current_session_context_class">thread</property>
2)调用getCurrentSession()方法:
不是调用SessionFactory.openSession()方法,而是调用SessionFactory.getCurrentSession()方法,获取Session对象,从当前的线程中获取当前Session对象。
3)当前线程中如果存在Session,则直接取出使用,如果不存在,会获取一个新的Session对象并将该对象与当前线程绑定。
——总结
1、事务管理
* 特性
* 隔离级别
* 丢失更新的解决方法
2、Hibernate中如何解决事务问题
* 设置隔离级别
* 悲观锁
* 乐观锁
3、本地线程绑定Session