zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    hlgoj 1766 Cubing
    Reverse Linked List
    String to Integer
    Bitwise AND of Numbers Range
    Best Time to Buy and Sell Stock III
    First Missing Positive
    Permutation Sequence
    Next Permutation
    Gray Code
    Number of Islands
  • 原文地址:https://www.cnblogs.com/wwwwyc/p/6375468.html
Copyright © 2011-2022 走看看