`

hibernate 事务 annoation

阅读更多

事务隔离

 
使用封锁技术,事务对申请的资源加锁,但是会影响数据库性能。根据数据对象封锁的程度,可以分成多种不同的事务隔离级别。
 
数据并发执行时,产生不一致的现象:
1
,丢失更新(Lost Update
 
两个事务读入同一数据并修改,然后提交修改,T2 提交的结果破坏了 T1 提交的结果,导致 T1 的修改丢失。
2
, 不可重复读
 
事务T1 读取数据后,事务T2 执行了同一数据的跟新操作,使得事务 T1 无法再现前一次读取的结果。
   
事务1 读取某一数据后,事务2 对该数据作了修改,事务1 再次读取时,得到数据和前一次不一致。
    ①
事务1 读取某一些记录后,事务2 删除了同一数据源的部分数据,事务1 再次读取时,发现某些记录丢失。
    ①
事务1 读取某一些记录后,事务2 插入了同一数据源的新数据,事务1 再次读取时,发现某些记录增加。
3
, 读数据
 
事务T1 修改某一数据,并将其写回物理数据库。事务T2 读取同一数据后,事务T1 由于某种原因被撤销,数据库将已经修改的数据恢复原值,导致事务T2 保持的数据和数据库中的数据产生了不一致。

  ANSI SQL-99
标准定义了下列隔离级别:
Hibernate
在配置文件中声明事务的隔离级别,Hibenate 获取数据库连接后,将根据隔离级别自动设置数据库连接为指定的事务隔离级别。
<property name="connection.isolation">8</property>
未提交读(Read Uncommitted):隔离事务的最低级别,只能保证不会读取到物理上损坏的数据。Hibernate配置:1;允许产生:123

已提交读(Read Committed):常见数据库引擎的默认级别,保证一个事务不会读取到另一个事务已修改但未提交的数据。Hibernate配置:2;允许产生:1
2

可重复读(Repeatable Read):保证一个事务不能更新已经由另一个事务读取但是未提交的数据。相当于应用中的已提交读和乐观并发控制。Hibernate配置:4;允许产生:
1

可串行化(Serializable):隔离事务的最高级别,事务之间完全隔离。系统开销最大。Hibernate配置:8;这种情况很容易造成死锁的问题,hibernate表现为:

Deadlock found when trying to get lock; try restarting transaction
2-3、并发控制类型

  根据使用的锁定策略和隔离等级,可以把事务的并发控制分为两种:

悲观并发控制
  
  用户使用时锁定数据。主要应用于数据争用激烈的环境中,以及发生并发冲突时用锁保护数据的成本低于回滚事务成本的环境中。
  Hibernate 的悲观锁定不在内存中锁定数据,由底层数据库负责完成。

乐观并发控制
  
  用户读取数据时不锁定数据。当一个用户更新数据时,系统将进行检查该用户读取数据后其他用户是否更改了该数据,是则产生一个错误,一般情况下,收到错误信息的用户将回滚事务并重新开始。主要用户数据争用不大,且偶尔回滚事务的成本低于读取数据时锁定数据的成本的环境中。

  Hibernate 中使用元素 version  timestamp 实现乐观并发控制模式的版本控制,并提供多种编程方式。版本是数据库表中的一个字段,可以是一个递增的整数,也可以是一个时间戳,它们对应 Java 持久化类的一个属性。事务提交成功后,Hibernate 自动修改版本号。如果另外一个事务同时访问同一数据,若发现提交前的版本号和事前载入的版本号有出入,则认为发生了冲突,事务停止执行,撤销操作,并抛出异常。应用程序必须捕捉该异常并做出一定的处理。
应用程序级别的版本控制
长生命周期会话的自动化版本控制
托管对象的自动化版本控制
定制自动化版本控制

 

 二 实际应用中我们使用Read Committed作为我们的事务级别 也就是 已提交读(Read Committed),因为如果用户 有权限 修改一个 数据 ,那 那么 就可以提交这个事务,这是系统需要解决的权限问题,由于这种情况会造成第二类数据丢失的情况,因此要配备乐观锁的机制,这种事物方法使用比较多。下面 举例实验:

1,例如A持久化后会被事务关联(事务针对修改,插入,不针对查询,如果对于一般不需要修改的表,如字典表,可以不配置事务,而是配置二级缓存来提高性能)

class A代码(先不加乐观锁,会造成第二类数据丢失):

 

@Entity
public class A {
        private int id;
        private int anum;
        private String aname;
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        public int getId() {
               return id;
        }
        //get..set
        
}

 

 

 hibernate配置:<property name="connection.isolation">2</property>

事先插入一条数据(a.setAnum(1);

测试代码:

 

public static void test(){
               
                new Thread(new Runnable(){//线程2,启动事务后不提交,然后让线程1启动
                       public void run() {
                               Session session = HibernateSessionFactory.getSession();
                               Transaction tt = session.beginTransaction();
                               System.out.println("t2 statr....");
                               A a = (A) session.get(A.class, 1);
                               System.out.println("未修改之前的num:"+a.getAnum());
                               a.setAnum(a.getAnum()+1);
                               session.update(a);
                               try {
                                      Thread.sleep(5000);//让出时间让线程1执行
                               } catch (InterruptedException e) {
                                      // TODO Auto-generated catch block
                                      e.printStackTrace();
                               }
                               tt.commit();
                               session.clear();//清除一级缓存
                               System.out.println("t2 cummit end....");
                                A a1 = (A) session.get(A.class, 1);
                                System.out.println("修改之后的num:"+a1.getAnum());
                               session.close();
                               
                       }
                       
               }).start();//正确结果为1+1=2

                new Thread(new Runnable(){
                        public void run() {
                                                      
                                                      Session session = HibernateSessionFactory.getSession();
                                                      Transaction tt = session.beginTransaction();
                                                      System.out.println("t1 statr....");
                                                      A a = (A) session.get(A.class, 1);
                                                      a.setAnum(a.getAnum()+2);
                                                      session.update(a);
                                                      tt.commit();
                                                      System.out.println("1 cummit end....");
                                                      session.clear();//清除一级缓存
                                                      session.close();
                                                      
                                              }
                                              
                                      }).start();//正确结果为1+1=3
               
        }

 

 

 打印信息:

 

t2 statr....
Hibernate: select a0_.id as id0_0_, a0_.aname as aname0_0_, a0_.anum as anum0_0_ from A a0_ where a0_.id=?//让出时间让t1执行
t1 statr....
Hibernate: select a0_.id as id0_0_, a0_.aname as aname0_0_, a0_.anum as anum0_0_ from A a0_ where a0_.id=?
未修改之前的num:1
Hibernate: update A set aname=?, anum=? where id=?
1 cummit end....
Hibernate: update A set aname=?, anum=? where id=?
t2 cummit end....
Hibernate: select a0_.id as id0_0_, a0_.aname as aname0_0_, a0_.anum as anum0_0_ from A a0_ where a0_.id=?
修改之后的num:2

 

 

 可以看出他t1本来应该是3但是被t2覆盖

 

 为此我们加上锁:

修改A(锁可以有两种,version,和时间锁,但是时间锁有个精确度问题)使用version

 

private int version;
...
@Version//使用version注释来表明版本控制
        public int getVersion() {
               return version;
        }

 

 

 测试(同样的测试代码):

打印信息:

 

t2 statr....
Hibernate: select a0_.id as id0_0_, a0_.aname as aname0_0_, a0_.anum as anum0_0_, a0_.version as version0_0_ from A a0_ where a0_.id=?
t1 statr....
Hibernate: select a0_.id as id0_0_, a0_.aname as aname0_0_, a0_.anum as anum0_0_, a0_.version as version0_0_ from A a0_ where a0_.id=?
未修改之前的num:1
Hibernate: update A set aname=?, anum=?, version=? where id=? and version=?
1 cummit end....
Hibernate: update A set aname=?, anum=?, version=? where id=? and version=?
Exception in thread "Thread-0" org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.eric.po.A#1]
        at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1792)
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2435)
        at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2335)
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2635)
        at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115)
        at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
        at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
        at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
        at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
        at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
        at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
        at com.eric.dao.Testcreate$1.run(Testcreate.java:139)
        at java.lang.Thread.run(Thread.java:619)

 

 

 此时乐观所就起作用了,防止了数据的丢失。针对异常可自行捕获。

 

 

 

 

 

 

 

2
1
分享到:
评论

相关推荐

    Spring Hibernate 事务处理 详细说明

    总结起来,Spring和Hibernate的事务处理涉及了Spring的声明式事务管理、事务的传播行为、隔离级别以及回滚规则等概念。通过整合这两者,我们可以构建高效、健壮的企业级应用程序,确保数据的完整性和一致性。了解并...

    详解Hibernate事务处理机制

    ### 详解Hibernate事务处理机制 #### 一、引言 Hibernate作为一款优秀的对象关系映射(ORM)框架,在Java开发领域扮演着极其重要的角色。它不仅简化了数据持久化的复杂性,还提供了一系列强大的功能来支持高效的...

    Spring Hibernate事务实例

    本教程将深入探讨如何在Spring框架中利用`TransactionInterceptor`进行声明式事务管理,与Hibernate集成实现高效的数据库事务控制。 首先,了解事务管理是至关重要的。事务是一组数据库操作,这些操作要么全部成功...

    Hibernate事务(源码)

    **Hibernate事务管理详解** 在Java开发中,尤其是在企业级应用中,事务管理是不可或缺的一部分。Hibernate作为一款流行的ORM(对象关系映射)框架,提供了强大的事务处理能力。本篇文章将深入探讨Hibernate中的事务...

    Hibernate 事务和并发控制

    本文将深入探讨Hibernate中的事务和并发控制,这对于开发高效、稳定的数据库应用至关重要。 首先,我们来理解Hibernate中的事务管理。在数据库操作中,事务是保证数据一致性的重要手段。一个事务包含了一组数据库...

    hibernate事务管理机制.doc

    【hibernate事务管理机制】是指在使用Hibernate框架进行数据库操作时,如何管理和协调事务的一系列规则和策略。事务管理是确保数据一致性、完整性和并发控制的重要机制。 **悲观锁**是预防性的锁定策略,它假设并发...

    spring hibernate 事务管理学习笔记(一)

    本文将深入探讨Spring与Hibernate整合时的事务管理,帮助你更好地理解和运用这些技术。 首先,Spring框架是Java企业级应用的基石,它提供了一种依赖注入(Dependency Injection,DI)的方式,使得组件之间的耦合度...

    在Spring中配置Hibernate事务

    在Spring框架中集成和配置Hibernate事务管理是企业级Java应用中的常见实践,它能提供高效且灵活的事务处理策略。Spring作为一款强大的依赖注入(DI)和面向切面编程(AOP)容器,能够轻松地管理和协调不同数据访问...

    hibernate事务,并发及缓存管理实例

    在Hibernate中,事务、并发控制和缓存管理是至关重要的概念,它们极大地影响了应用程序的性能和数据一致性。 一、Hibernate事务管理 在数据库操作中,事务确保了数据的一致性和完整性。Hibernate提供了四种事务隔离...

    spring hibernate 事务管理学习笔记(二)

    在本篇“Spring Hibernate 事务管理学习笔记(二)”中,我们将深入探讨Spring框架与Hibernate集成时如何实现高效、安全的事务管理。这是一篇关于源码分析和技术工具使用的文章,适合对Java开发和数据库操作有基础...

    Hibernate编程式事务与Spring Aop的声明式事务(spring与hibernate集成)

    本篇文章将重点讨论如何在Spring框架中集成Hibernate,并探讨编程式事务管理和Spring AOP的声明式事务。 首先,让我们理解Spring与Hibernate的集成。为了整合这两个库,你需要在Spring配置文件中定义Hibernate的...

    Spring+Hibernate注解事务实例

    本实例将深入探讨如何结合Spring的注解声明式事务管理与Hibernate的数据访问技术,构建一个完整的事务处理系统。 Spring框架以其灵活的依赖注入(DI)和面向切面编程(AOP)闻名,它允许开发者将事务管理从业务逻辑...

    spring mvc+hibernate 实现事务管理(全注解版)

    2. **Hibernate事务**: Hibernate本身也提供了一种事务管理机制,但在Spring环境中,我们通常使用Spring的事务管理器来协调。当@Transactional注解应用于方法上,Spring会在该方法执行前后自动管理事务的开始和结束...

    spring整合hibernate实现事务处理

    本篇文章将详细探讨如何通过Spring整合Hibernate来实现事务处理,重点介绍注解方式和XML配置方式。 首先,我们了解事务处理在数据库操作中的重要性。事务是一组操作,这些操作要么全部成功,要么全部失败,确保数据...

    spring mvc+hibernate实现事务管理(配置文件版)

    本项目是关于如何使用Spring MVC与Hibernate结合来实现事务管理的实践教程,通过MyEclipse自动生成所需的包和配置文件。这里将详细讲解这一过程,以及涉及到的关键知识点。 首先,Spring MVC作为Spring框架的一部分...

    Hibernate事务和并发控制

    事务和并发控制是数据库管理中的核心概念,特别是在使用ORM框架如Hibernate时,理解它们的工作原理至关重要。本文将深入探讨Hibernate中的事务管理和并发控制。 首先,事务是数据库操作的基本单位,它保证了数据的...

    hibernate事务

    Hibernate事务管理是Java开发中非常重要的一个环节,尤其是在企业级应用开发中,它与数据库的交互密切相关,确保数据的一致性和完整性。Hibernate作为一款流行的ORM(对象关系映射)框架,提供了一种方便的方式来...

    JDBC和hibernate事务的详解

    **JDBC与Hibernate事务详解** 在Java开发中,数据库事务管理是确保数据一致性、完整性和原子性的重要机制。本讲解将深入探讨JDBC(Java Database Connectivity)和Hibernate两种不同的技术在处理事务时的方法和特点...

    hibernate事务源码

    1.什么是Hibernate? (1) hibernate一种ORM工具,是连接 java 应用程序 和关系数据库的中间件,这是对JDBC的封装,主要负 责 java 对象的持久化. (2)Hibernate是自动根据xml配置完成对象映射关系, 并根据提供的API...

    Could not roll back Hibernate transaction.doc

    Hibernate事务回滚失败解决方案 Hibernate是一个流行的Java持久层框架,它提供了对数据库的操作和事务管理机制。然而,在使用Hibernate时,可能会遇到事务回滚失败的问题,本文将详细介绍该问题的原因和解决方法。 ...

Global site tag (gtag.js) - Google Analytics