• 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

  • 相关阅读:
    第40次全国计算机等级考试监考
    [再寄小读者之数学篇](2014-07-27 打印错误吧)
    日积月累的名典[2014-10-7]
    2014年全球“高被引科学家”数学类名单
    年轻尼姑的19句话
    PostgreSQL的 initdb 源代码分析之十六
    PostgreSQL的 initdb 源代码分析之十五
    PostgreSQL的 initdb 源代码分析之十四
    PostgreSQL的 initdb 源代码分析之十三
    PostgreSQL的 initdb 源代码分析之十二
  • 原文地址:https://www.cnblogs.com/wwwwyc/p/6375468.html
Copyright © 2020-2023  润新知