首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

事宜在Hibernate以及JPA中的应用(一)

2012-12-22 
事务在Hibernate以及JPA中的应用(一)首先需要声明的是,hibernate本身没有事务功能。它只是借助JDBC事务,或

事务在Hibernate以及JPA中的应用(一)


首先需要声明的是,hibernate本身没有事务功能。它只是借助JDBC事务,或者JTA事务来实现事务的管理,它只是封装了事务的使用方法。一般事务控制定界到service层,但是为了方便,以下的代码将事务代码放在Dao层。事务在Hiibernate中的应用具体可以分为一下三部分:



1 JDBC事务在Hibernate的应用。如果我们系统不需要分布式的话,那么就可以采用JDBC事务来提供事务服务。要想在Hibernate里使用 JDBC事务,我们必须要配置如下属性:hibernate.transaction.factory_class=org.hiberante.transaction.JDBCTransactionFactory.

在此种情况下典型的编码方式如下:
Java代码

   public class XXXDao ...{                  Session session ;          Transaction tx ;              public void crudOperation(){                  try{                       session = HibernateUtil.getCurrentSession();             tx = session.beginTransaction();             //完成具体的CRUD操作。            tx.commit();                  }catch(RuntimeException e){             tx.rollback();         }finally{                     this.getSession().close();         }                    }    }  public class XXXDao ...{Session session ;Transaction tx ;public void crudOperation(){try{session = HibernateUtil.getCurrentSession();tx = session.beginTransaction();//完成具体的CRUD操作。tx.commit();}catch(RuntimeException e){tx.rollback();}finally{this.getSession().close();}}}

在此种情况下,Hibernate的数据库连接可以由容器来管理,也可以自己管理一个数据库连接池,并且只有当事务开始的时候才获得 connection.需要注意的是,tx.beginTransaction(),此语句实际上是将获得connection的自动提交模式关闭,也就是connection.setAutoCommit(false)。



2 JTA事务在Hibernate中的应用。如果要想使用JTA事务提供的分布式事务服务,那么必须要做以下事情:

首先,需要确保相对应的JDBC驱动程序支持XAResource接口,因为只有支持此接口的JDBC Driver才能纳入JTA事务管理器的管理。

其次,需要更改配置如下:

hibernate.transaction.factory_class=org.hiberante.transaction.JTATransactionFactory.

hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup.(此配置根据自己的JavaEE AS来配置).

确保以上两个条件后,就需要考虑选择JTA provider了,是选择JavaEE服务器来提供JTA服务呢,还是通过开源的JTA组件来提供服务。如果采用开源的组件的话,可以采用如JBoss 的JTA组件等。如果采用JavaEE服务器的话,则可以直接受益与Application server提供的JTA服务了。

需要注意的是在这种情况下,hibernate不再管理数据库连接池了,它需要通过JNDI来获取JTA提供者暴漏的连接池服务。

在此种模式下,编程模型可以采用如下两种:

1)利用hibernate的Transaction接口。典型的代码如下:


Java代码

   public class XXXDao ...{ 
         
        Session session ; 
       Transaction tx ; 
     
       public void crudOperation(){ 
        
       try{ 
        
          session = HibernateUtil.getCurrentSession(); 
           tx = session.beginTransaction(); 
           //完成具体的CRUD操作。 
           tx.commit(); 
        
     }catch(RuntimeException e){ 
        
          tx.rollback(); 
       }finally{ 
        
          this.getSession().close(); 
      } 
            
       } 
   } 

public class XXXDao ...{

Session session ;
Transaction tx ;

public void crudOperation(){

try{

session = HibernateUtil.getCurrentSession();
tx = session.beginTransaction();
//完成具体的CRUD操作。
tx.commit();

}catch(RuntimeException e){

tx.rollback();
}finally{

this.getSession().close();
}

}
}

如果采用Hibernate的原生接口的话,那么不需要应用程序flush session和关闭session了,因为在模型下,hibernate内部会在事务提交的时候自动flush和close session.但是这样做不好的地方就是将应用程序绑定到hiberante原生(Native)接口,不便于系统的移植,所以为了方便系统移植,以及将事务服务的提供留给应用程序部署者来完成,我们可以采用standard JTA接口。JTA编程接口典型的代码如下:
Java代码
   public class XXXDao ...{                  Session session ;         UserTransaction utx = (UserTransaction)ServiceLocator.getUserTransaction("JNDIName") ;               public void crudOperation(){                    try{                   utx.begin():             session = HibernateUtil.getCurrentSession();                         //完成具体的CRUD操作。             utx.commit();            session.flush();//此时需要程序来flush session                  }catch(RuntimeException e){                     utx.rollback();            //日志记录等         }finally{                     this.getSession().close();         }                      }     }  public class XXXDao ...{Session session ;UserTransaction utx = (UserTransaction)ServiceLocator.getUserTransaction("JNDIName") ;public void crudOperation(){try{  utx.begin():session = HibernateUtil.getCurrentSession();//完成具体的CRUD操作。utx.commit();session.flush();//此时需要程序来flush session}catch(RuntimeException e){utx.rollback();//日志记录等}finally{this.getSession().close();}}} 


此时值得注意的时,需要应用程序来刷新session,如果想要激活自动刷新和自动关闭session的功能,需要配置如下两个属性:

* hibernate.transaction.flush_before_completion和 hibernate.transaction.auto_close_session为true.这样以来当JTA事务提交和回滚的时候 Hibernate就会自动刷新和关闭session.



如果觉得以上代码不够美观的话,那是正常的,因为代码中充斥着try,catch语句,以及将事务处理的代码侵入到了业务代码中。如何避免这些烦人的try ,catch语句,以及事务处理代码,就需要比较流行的AOP来解决。如果采用AOP的话,建议采用现成的AOP框架来实现,比如spring就支持 hibernate的声明式事务管理,当然也可以采用代理等模式来自己实现,看系统需要和个人爱好。



3.采用容器管理事务(CMT).如果采用JavaEE AS的话,我们就可以直接使用EJB容器提供的声明式事务管理功能了。在此种模式下,其实底层事务还是JTA,不过事务控制是由容器来控制,应用程序只需要负责业务核心就OK了。如果采用CMT的话,可以通过session bean来封装 hibernate session,这样可以通过EJB的Annotation来注解业务方法,这样以来就不需要我们关心事务代码了,只需要配置支持XA 标准的数据源就好了。不过此时的事务工厂类要配置为CMTTransactionFactory.

热点排行