当前位置:编程学习 > JAVA >>

hibernate的事务管理

在讲解hibernate的事物管理之前,我们必须首先明白一些基本的概念,以此帮助理解,为什么要事物管理这个东西,有它之后有什么用,它有哪些基本特性或者限制,
 
那么第一点,我们该知道的就是事物的4个基本特性,也就是我们常说的ACID【原子性,一致性,隔离性,持久性】;
 
第二点,应该知道的是,事物的隔离级别,即通过某种机制,在并发运行的多个事物之间进行分隔,使其保持执行时的独立性。一般分为Read Uncommitted,   Read Committed ,  Repeatable Read,  Serializable这四个隔离级别,这四种隔离级的严密程度是一次递增的,同事它的性能也是依次下降,在脏读取,不可重读,和虚读,这三个中数据库可能出现漏洞的情况下,这四个级别采取的应对措施是不同的,也就是说,这四个隔离级下,这三种情况发生的可能性是,1.可能脏读,可能重读,可能虚读;2.不可能脏读,可能重读,可能虚读; 3.不可能脏读,不可能重读,可能虚读 4.三种漏洞全都不可能发生。所以日常使用时,需根据实际情况取舍,以保持系统的最佳平衡。
 
hibernate是jdbc轻量级的封装,本身不具备事务管理的能力,在事物管理层面,一般是委托于底层的jdbc和jta来完成调度的。默认事物处理机制是基于jdbc transaction的,当然,我们也能通过配置jta来实现:
 
Xml代码
<hibernate-configuration> 
    <session-factory> 
        ........ 
            <property name="hibernate.transaction.factory_class"> 
                     net.sf.hibernate.transaction.JTATransactionFactory  //JTA 
                    <!--net.sf.hibernate.transaction.JDBCTransactionFactory-->   //JDBC 
            </property> 
        ........ 
     </sesssion-factoty> 
</hibernate-configuration> 
 
  将事物委托给jdbc处理,无疑是最简单的方式,hibernate支持它做默认方式,其事物的封装,也非常简单,比如当我们在处理这段代码时:
 
Java代码
session = sessionFactory.openSession(); 
Transaction tx=session.beginTransaction(); 
...... 
tx.commit(); 
 
  而从jdbc事物层面而言,实际上做的是:
 
Java代码
Connection dbconn=getConnection(); 
dbconn.setAutoCommit(false); 
...... 
dbconn.commit(); 
 
  就这么简单,换了个说法,把hibernate的提交方式,在底层用原生的jdbc进行了提交,这里需要注意的是在openSession()的时候,底层的jdbc的AutoCommit属性已被关闭了,除非jdbc连接去commit,否则执行的操作将不会对数据库产生任何效果,这里那就需要我们去显示执行tx.commit()了[非事物性数据库除外,如Mysql ISam]
 
而JTA与jdbc的事物的最大差异,在于它提供了跨session的事物管理能力。jdbc事物由Connection管理,事物的周期限于Connection的生命周期。而JTA则由JTA容器实现,容器可对当前的众多Connection进行调度,于是它可横跨多个Connection生命周期,于是也提供了跨session的能力。
 
比如我们下面这段代码,在jdbc的事物下完全正确的,但是在jta下就会产生问题:
 
Java代码
class ClassA{ 
    public void save(User user){ 
         Session session=sessionFactory.openSession(); 
         Transaction tx=session.beginTransaction(); 
         session.save(user); 
         tx.commit(); 
         
        session.close(); 
    } 

Java代码
<pre class="java" name="code">class ClassB{ 
    public void save(Order order){ 
         Session session=sessionFactory.openSession(); 
         Transaction tx=session.beginTransaction(); 
         session.save(order); 
         tx.commit(); 
         
        session.close(); 
    } 
}</pre> 
class ClassC{ 
    public void save(){ 
        ..... 
        UserTransaction tx=(UserTranscation)(new InitialContext().lookup("....")); 
         ClassA.save(user); 
Java代码
         ClassB.save(oreder); 
         tx.commit(); 
         
       ...... 
    } 

  这里的问题是,ClassA和B调用了hibernate的Transaction功能。而在hibernate的JTA分装中,Session.beginTransaction同样也执行了InitialContext.lookup去获得UserTransaction的实例,而在tx.commit的时候,ClassA和B都企图声明自己的事物,从而导致错误,因为我们知道,jdbc的事物,是不能够跨connection,跨session的。而假使使用jta,那么我们则可以修改上面代码,实现操作:
Java代码
class ClassA{ 
    public void save(User user){ 
         Session session=sessionFactory.openSession(); 
         session.save(user); 
        session.close(); 
    } 

 
class ClassB{ 
    public void save(Order order){ 
         Session session=sessionFactory.openSession(); 
         session.save(order); 
         
        session.close(); 
    } 

 
class ClassC{ 
    public void save(){ 
     ..... 
         Session session=sessionFactory.openSession(); 
         Transaction tx=session.beginTransaction(); 
         ClassA.save(user); 
         ClassB.save(order); 
         tx.commit(); 
         
        session.close(); 
    } 

 
在EJB中使用JTA Transaction无疑最为简单,我们只需要将save方法的属性声明为Required,Ejb容器就会自动的维护并执行过程中的事物。www.zzzyk.com
补充:软件开发 , Java ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,