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

            1—Read uncommitted isolation
            2—Read committed isolation
            4—Repeatable read isolation
            8—Serializable isolation
 

    4)写问题
        数据更新丢失问题,当两个事务更新了同一条记录,会导致后提交的事务覆盖前提交的事务。
        可以使用悲观锁或乐观锁来解决:
        悲观锁:(排它锁)
            当前事务会锁定当前记录,其他事务无法访问。
            // 使用悲观锁(排它锁)

            Customer customer = (Customer) session.get(Customer.class, 1, LockMode.UPGRADE);
 

        乐观锁:
            会通过一个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

posted @ 2017-02-07 18:28  WWWYC  阅读(223)  评论(0编辑  收藏  举报