事务是一系列持久化动作的集合,如果事务成功,则更改保存;如果事务失败,则
事务回滚;无论处于任何一种状态,数据保持干净与一致。
事务具有隔离性,原子性,耐久性,并发操作的正确性。

普通JDBC事务

事务在JDBC实现是通过下面方式:

setAutoCommit(false);
  commit();
  rollback();

这种方式是一种低伸缩性(scalability)架构,因为每个事务要绑定一个JDBC连接,也就是一个Connection对象。

伸缩性优化

JavaEE的JTA+JTA兼容性运行时环境解决此类问题,它能够提供所有JDBC事务的功能同时拥有以下几个新的特点:

  • 支持多个数据库上的数据进行操作在同一事务出现
  • 数据库连接对象管理(申请和释放,高伸缩性来自这个特点)
    目前为止利用Hibernate事务接口你可能这样写:
Session session=null;
  Transaction transaction=null;
  try{
      session=sessionFactory.openSession();
      transaction=session.beginTransaction();
      //do something
      transaction.commit();
  }catch(RuntimeException ex){
       try{
          tx.rollback();
       }catch(RuntimeException ex){
               log.error("can't roolback",ex);
       }
  }
  session.close();

Hibernate底层通常使用PreparedStatement来执行SQL,Session对象通常保持着一个数据库连接(Connection对象),不过和数据库Connection对象一样保持一个连接,为什么使用Hibernate来增加编写复杂性?

原因就在于需要一个开关(一些配置)你就可以利用Hibernate来使用JTA,在JavaEE应用服务器下,你可以实现多数据源事务操作。实际上这些配置是将Hiberante配置为JTA模式。

//切换JTA模式
 hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory;
 //这个设置JavaEE环境(JTA实现环境)
 hibernate.transaction.manager_look_up_class=org.hibernate.transaction.JBossTransaction-ManagerLookup

但是还需要一个额外的步骤就是JNDI配置一个全局注册项,自己Google集成JTA

配置完这些之后,Hibernate不再是连接管理者,而是JavaEE环境(运行时容器),连接通过JNDI来获取。JNDI配置你的数据源。

现在所有都配置好了,看一下多个数据库事务处理

多数据库事务处理

多数据库处理先使用JNDI来查找与Hibernate等价的JTA 的UserTranscation对象。

UserTranscation utx=(UserTransaction)new InitialContext().lookup("yourregistryURL");
  Session first=null;
  Session second=null;
  try{
     utx.begin();
     first=firstDataBase.openSession();
     second=secondDataBase.openSession();
     //do something

     //注意这里
     first.flush();
     second.flush();
     utx.commit();
  }catch(RuntimeException e){
      try{
          tx.rollback();
       }catch(RuntimeException ex){
          log.error("can't roolback",ex);
       }
  }finally{
     first.close();
     second.close();

  }

考虑到同步化,Session通常是惰性的,也就是直到事务关闭,Session才会发射所有的DML语句到数据库,flush()方法负责释放。
使用以下配置来简化代码:

hibernate.transaction.flush_before_completion=true;
  hibernate.transaction.auto_close_session=true;

以上的语句flush()close()方法就都不用执行了!

综合分析一下数据库连接的变化状态:
原来Session保持数据库连接的粒度对比

方式

粒度

普通JDBC

事务粒度

JTA配置状态

语句(Statement)粒度