`

hibernate 事物

阅读更多
Hibernate事务与并发问题处理(乐观锁与悲观锁)
一、数据库事务的定义
  数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。
  1. 原子性(atomic),事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行
  2. 一致性(consistent),事务在完成时,必须使所有的数据都保持一致状态。
  3. 隔离性(insulation),由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。
  4. 持久性(Duration),事务完成之后,它对于系统的影响是永久性的。
二、数据库事务并发可能带来的问题
  如果没有锁定且多个用户同时访问一个数据库,则当他们的事务同时使用相同的数据时可能会发生问题。由于并发操作带来的数据不一致性包括:丢失数据修改、读”脏”数据(脏读)、不可重复读、产生幽灵数据:
假设数据库中有如下一张表:

  1. 第一类丢失更新(lost update): 在完全未隔离事务的情况下,两个事物更新同一条数据资源,某一事物异常终止,回滚造成第一个完成的更新也同时丢失。

  在T1时刻开启了事务1,T2时刻开启了事务2,在T3时刻事务1从数据库中取出了id="402881e535194b8f0135194b91310001"的数据,T4时刻事务2取出了同一条数据,T5时刻事务1将age字段值更新为30,T6时刻事务2更新age为35并提交了数据,但是T7事务1回滚了事务age最后的值依然为20,事务2的更新丢失了,这种情况就叫做"第一类丢失更新(lost update)"。
  2. 脏读(dirty read):如果第二个事务查询到第一个事务还未提交的更新数据,形成脏读。

  在T1时刻开启了事务1,T2时刻开启了事务2,在T3时刻事务1从数据库中取出了id="402881e535194b8f0135194b91310001"的数据,在T5时刻事务1将age的值更新为30,但是事务还未提交,T6时刻事务2读取同一条记录,获得age的值为30,但是事务1还未提交,若在T7时刻事务1回滚了事务2的数据就是错误的数据(脏数据),这种情况叫做" 脏读(dirty read)"。
  3. 虚读(phantom read):一个事务执行两次查询,第二次结果集包含第一次中没有或者某些行已被删除,造成两次结果不一致,只是另一个事务在这两次查询中间插入或者删除了数据造成的。

  在T1时刻开启了事务1,T2时刻开启了事务2,T3时刻事务1从数据库中查询所有记录,记录总共有一条,T4时刻事务2向数据库中插入一条记录,T6时刻事务2提交事务。T7事务1再次查询数据数据时,记录变成两条了。这种情况是"虚读(phantom read)"。
  4. 不可重复读(unrepeated read):一个事务两次读取同一行数据,结果得到不同状态结果,如中间正好另一个事务更新了该数据,两次结果相异,不可信任。

  在T1时刻开启了事务1,T2时刻开启了事务2,在T3时刻事务1从数据库中取出了id="402881e535194b8f0135194b91310001"的数据,此时age=20,T4时刻事务2查询同一条数据,T5事务2更新数据age=30,T6时刻事务2提交事务,T7事务1查询同一条数据,发现数据与第一次不一致。这种情况就是"不可重复读(unrepeated read)"。
  5. 第二类丢失更新(second lost updates):是不可重复读的特殊情况,如果两个事务都读取同一行,然后两个都进行写操作,并提交,第一个事务所做的改变就会丢失。

  在T1时刻开启了事务1,T2时刻开启了事务2,T3时刻事务1更新数据age=25,T5时刻事务2更新数据age=30,T6时刻提交事务,T7时刻事务2提交事务,把事务1的更新覆盖了。这种情况就是"第二类丢失更新(second lost updates)"。

三、数据库事务隔离级别
为了解决数据库事务并发运行时的各种问题数据库系统提供四种事务隔离级别:
1. Serializable 串行化
2. Repeatable Read 可重复读
3. Read Commited 可读已提交
4. Read Uncommited 可读未提交
隔离级别与并发性能的关系:

每一个隔离级别可以解决的问题:


四、使用Hibernate设置数据库隔离级别
在Hibernate的配置文件中可以显示的配置数据库事务隔离级别。每一个隔离级别用一个整数表示:
8 - Serializable 串行化
4 - Repeatable Read 可重复读
2 - Read Commited 可读已提交
1 - Read Uncommited 可读未提交
在hibernate.cfg.xml中使用hibernate.connection.isolation参数配置数据库事务隔离级别。

五、使用悲观锁解决事务并发问题
  悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
  一个典型的依赖数据库的悲观锁调用:select * from account where name=”Erica” for update这条 sql 语句锁定了 account 表中所有符合检索条件( name=”Erica” )的记录。本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。悲观锁,也是基于数据库的锁机制实现。
在Hibernate使用悲观锁十分容易,但实际应用中悲观锁是很少被使用的,因为它大大限制了并发性:

图为Hibernate3.6的帮助文档Session文档的get方法截图,可以看到get方法第三个参数"lockMode"或"lockOptions",注意在Hibernate3.6以上的版本中"LockMode"已经不建议使用。方法的第三个参数就是用来设置悲观锁的,使用第三个参数之后,我们每次发送的SQL语句都会加上"for update"用于告诉数据库锁定相关数据。

LockMode参数选择该选项,就会开启悲观锁。

  T1,T2时刻取款事务和转账事务分别开启,T3事务查询ACCOUNTS表的数据并用悲观锁锁定,T4转账事务也要查询同一条数据,数据库发现该记录已经被前一个事务使用悲观锁锁定了,然后让转账事务等待直到取款事务提交。T6时刻取款事务提交,T7时刻转账事务获取数据。

六、使用乐观锁解决事务并发问题
  相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个"version"字段来实现。
  乐观锁的工作原理:读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
Hibernate为乐观锁提供了3中实现:
1. 基于version
2. 基于timestamp
3. 为遗留项目添加添加乐观锁
配置基于version的乐观锁:


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.suxiaolei.hibernate.pojos.People" table="people">
        <id name="id" type="string">
            <column name="id"></column>
            <generator class="uuid"></generator>
        </id>
       
        <!-- version标签用于指定表示版本号的字段信息 -->
        <version name="version" column="version" type="integer"></version>

        <property name="name" column="name" type="string"></property>
       
    </class>
</hibernate-mapping>


配置基于timestamp的乐观锁:


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.suxiaolei.hibernate.pojos.People" table="people">
        <id name="id" type="string">
            <column name="id"></column>
            <generator class="uuid"></generator>
        </id>
       
        <!-- timestamp标签用于指定表示版本号的字段信息 -->
        <timestamp name="updateDate" column="updateDate"></timestamp>

        <property name="name" column="name" type="string"></property>
       
    </class>
</hibernate-mapping>


遗留项目,由于各种原因无法为原有的数据库添加"version"或"timestamp"字段,这时不可以使用上面两种方式配置乐观锁,Hibernate为这种情况提供了一个"optimisitic-lock"属性,它位于<class>标签上:


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.suxiaolei.hibernate.pojos.People" table="people" optimistic-lock="all">
        <id name="id" type="string">
            <column name="id"></column>
            <generator class="uuid"></generator>
        </id>

        <property name="name" column="name" type="string"></property>
    </class>
</hibernate-mapping>


将该属性的值设置为all,让该记录所有的字段都为版本控制信息。
分享到:
评论

相关推荐

    Hibernate 事物隔离级别 深入探究

    Hibernate 事务隔离级别 深入探究 在 Hibernate 中,事务隔离级别是指数据库系统提供的一种机制,以解决并发事务带来的问题。为了确保数据库的可靠性和一致性,Hibernate 提供了四种事务隔离级别,分别是 ...

    对Hibernate事物的理解

    **对Hibernate事务的理解** 在Java应用开发中,尤其是在企业级应用中,数据库操作是不可或缺的一部分。Hibernate作为一种流行的ORM(对象关系映射)框架,极大地简化了数据库操作,但同时也引入了事务管理的概念。...

    struts2+spring+hibernate 事物实例完整的例子

    Struts2、Spring 和 Hibernate 是三个著名的开源框架,它们在Java Web开发中有着广泛的应用。Struts2作为MVC框架负责处理用户请求和展现视图,Spring则提供强大的依赖注入和事务管理功能,而Hibernate是ORM(对象...

    hibernate缓存和事务

    Hibernate 是一个流行的对象关系映射(ORM)框架,它允许Java开发者使用面向对象的方式来操作数据库。在Java应用程序中,Hibernate 提供了一种便捷的方式,将数据模型类与数据库表进行映射,使得开发者无需直接编写...

    spring 整合hibernate的事物配置.pdf

    spring 整合hibernate的事物配置

    Spring+Hibernate 声明式事务

    本资源主要是结合博文 Spring+Hibernate: 声明式事务 http://blog.csdn.net/ManagementAndJava/article/details/78050519 的源代码,主要是讲解了spring4.3和hibernate5.2.11集成实现原理;

    hibernate源码分析一[启动过程]

    它将诸如数据库连接提供者(`ConnectionProvider`)、事物处理方式、缓存策略等转换为Java对象,便于后续使用。 #### Configuration类 `Configuration`类是Hibernate配置的核心,它负责读取并解析`hibernate.cfg....

    夏昕.深入浅出Hibernate.rar

    4. Session和Transaction:介绍Session的概念,它是Hibernate与数据库交互的主要接口,以及Transaction的管理,包括事物的隔离级别和回滚操作。 5. CRUD操作:详细演示如何使用Hibernate进行创建(Create)、读取...

    Spring+freemarker+Hibernate搭建

    一个完整的Spring+Hibernate+FreeMarker环境的搭建过程。 包括了国际化配置、缓存配置、事物配置等功能

    hibernate + mysql数据库项目必须的jar包

    3.12-0.GA.jar)、java跨数据库事物处理接口(jta-1.1.jar)、以及slf4j-api-1.6.1.jar、hibernate-jpi-1.6.1.jar、log4j-1.2.17.jar、slf4j-log4j12-1.7.25.jar,mysql数据驱动包-mysql-connector-java-5.0.8-bin.jar

    spring配置文档

    整合ssh框架的配置文件,有关hibernate事物 注解的配置文档

    Hibernate3.2官方中文参考手册.pdf 和Hibernate3.1_DOC_CN.chm中文版

    这个版本引入了对JPA的初步支持,同时增强了对事物(Transactions)、缓存(Caching)和查询的处理。事务管理是数据库操作的核心,Hibernate通过编程式和声明式两种方式来管理事务,确保数据的一致性和完整性。缓存...

    struts+spring+hibernate基础整合包+数据库Mysql+C3p0

    资源中包含ssh整合的基础java包可以进行基础开发,如果需要额外的功能,则需...叫做Spring MVC,同时为了很好的处理事物,Spring集成了Hibernate,使事物管理从Hibernate的持久层提升到了业务层,使用更加方便和强大。

    Spring3+Dwr+JdbcTemplate(拦截器方式实现防止重复提交)

    1.针对SpringMVC注解的配置,可起到入门的作用 ...3.Spring+Hibernate事物管理 4.Spring实现DWR注解方式的应用配置 5.Spring配置拦截器 6.Spring通过拦截器实现防止重复提交实例 对学习,会起到非常好的效果

    struts1,hibernate,spring整合demo1

    5. **事物管理**:在数据库操作中,事物是确保数据完整性和一致性的关键。Spring提供了PlatformTransactionManager接口,实现如DataSourceTransactionManager,用于管理数据库事务。在SSH整合中,通常会在Service层...

    hibernate抓取策略和懒加载案例

    然而,需要注意的是,如果在事物之外访问懒加载属性,可能会抛出`LazyInitializationException`,因为此时没有活动的Session可以执行SQL查询。为了避免这种情况,我们可以使用Open Session in View(OSIV)模式或者...

    spring4.0和hibernate4.0整合框架

    spring4.0和hibernate4.0框架的标准整合,此框架实现了hibernate根据实体自动创建表(前提是你要在mysql中创建名为testspring的库),spring的aop拦截功能,帮助了解aop,和spring事物控制,异常回滚以及junit4的测试...

    注释事物控制

    本篇文章将详细探讨“注释事物控制”在Spring MVC与Hibernate集成环境下的应用。 首先,我们来了解Spring中的事务管理。Spring提供了两种主要的事务管理方式:编程式事务管理和声明式事务管理。编程式事务管理通过...

    hibernate基本配置

    **hibernate基本配置** Hibernate 是一款强大的Java持久层框架,它简化了数据库与Java对象之间的交互,使得开发者可以...在实际开发中,还可以根据需求进一步配置事物隔离级别、第二级缓存策略、性能优化等高级特性。

    在SSH中使用事物包括SSH的搭建和配置;事物的配置;注释详细

    在SSH(Struts2、Spring、Hibernate)框架组合中,事务管理是确保数据一致性与完整性的关键机制。SSH是一个常见的Java Web开发栈,用于构建高效、模块化且可维护的应用程序。下面我们将深入探讨SSH中的事务管理和...

Global site tag (gtag.js) - Google Analytics