java事务实现世界可分为两种
一种是jdbc事务,也叫本地事务,令外一种是JTA事务,也叫全局事务。简要介绍下JTA API
javax.transaction.Status JTA事务状态,使用方式 常被作为判断条件做处理
javax.transaction.Synchronization 定义了事务完成前后改做的事,使用方式一般是先注册,在适当的时机调javax.transaction.Transaction 定义了操作全:事务提交,回滚,绑定或解绑资源事务与资源,获取状态,设置回滚,同步
javax.transaction.TransactionManager定义了事务的所有动作,一般由应用服务器采用jts实现
javax.transaction.TransactionSynchronizationRegistry定义了同步,但是同步的调用时机更接近2阶段提交,也就是说beforeComplete晚于Transaction注册的beforeComplete执行,afterComplete早于Transction的afterComplete执行
javax.transaction.UserTransaction提供给应用客户端化分事务边界的方法
javax.transaction.xa.XAResource定义了资源管理器与事务管理器的通信
javax.transaction.xa.Xid定义了资源事务关联的唯一标识,就好比树的枝干,每个资源管理器做的事就对应一条枝干的标识,而所有的枝干都长在一个树上象征着在每个资源管理器上做的事就对应着整颗树。Xid中包括全局事务格式,标识,分支标识。
为了更好的理解JTA实现,可参看更好的理解JTA。
org.hibernate.Transaction统一了各种事务的具体实现
JDBCTransaction
JTATransaction
CMTTransaction(事务托管给应用服务器完成)
三者都认为一个session只能允许同一时刻只能由一个未提交事务,实现中大量代码主要体现在事务提交前前后后的同步问题,我们将同步分为本地同步和JTA同步,之所以分开讨论,是因为这两种同步不能同时存在以上三种之一实现中。
如果条件flushBeforeCompletionEnabled||autoCloseSessionEnabled||connectionReleaseMode ==ConnectionReleaseMode.AFTER_TRANSACTION,即事务完成之前是否flush session,事务完成之后事务自动关闭 session,连接释放是否在提交事务之后 不为真,那么认为本地同步;
如果为真,则进行如下判断
   如果采用的实现类是JBCTransaction或者TransactionManager没找到或者事务已经完成(提交或回滚,未激活等)或事务被标识为回滚,则为本地同步
   否则,为JTA同步。
JDBCTransaction中
   如果为本地同步并且flushmode !=Flushmode.Never则刷新session
   如果为本地同步,则执行org.hibernate.jdbc.JDBCContext中的beforeTransactionCompletion和afterTransactionCompletion,同时执行synchronizations集合中的各个同步类(都是javax.transaction.Synchronization实现)
JTATransaction中
   如果不是JTA同步,则认为是本地同步
   如果是JTA同步,则同步方法的执行又JTA实现自动完成,hibernate不干预
   如果是本地同步或!flushBeforeCompletionEnabled并且flushModel!=flushModel.Never,则刷新session
   如果是本地同步并且JTA事务是通过Transaction begin启动,则执行beforeTransactionCompletion
   如果JTA不是通过Transaction begin启动,则Transaction commit并不会真正触发提交
   如果是本地同步,则执行afterTransactionCompletion
CMTTransaction中
   如果不是JTA同步,Transaction begin抛出异常
   如果是JTA同步并且!flushBeforeCompletionEnabled并且flushModel!=flushModel.Never,则刷新缓存
三种实现的总结:
   JDBCTransaction只会执行本地同步
    它通过java.sql.Connection实现,并会执行JdbcContext.beforeTransactionCompletion和afterTransactionCompletion
    JTATransaction既可以进行JTA同步,也可进行本地同步;
     它通过userTransaction实现,
但在调用Transaction begin方法之前,事务允许通过userTransaction.begin开始,如果不是调用Transaction begin开启事务的,那自然就不会调用JdbcContext.beforeTransactionCompletion。如果是本地同步的话,还可以调用jdbcContext.afterTransactionCompletion
    CMTTransaction不会进行实质性的事务开始,提交,回滚,超时,只设置回滚标志,当调用Transaction begin方法时会调用registerSynchronizationIfPossible而此时会在事务管理器上注册同步org.hibernate.transaction.CacheSynchronization,间接调用调用JdbcContext.beforeTransactionCompletion和afterTransactionCompletion,
三种事务的创建由对应的JDBCTransactionFactory,JTATransactionFactroy,CMTTransactionFactory完成
这三者区别在
  connectionReleaseMode
     JTATransactionFactroy和CMTTransactionFactory连接释放模式执行每条语句后释放连接,JDBCTransactionFactory事务提交后释放,因此jta事务连接的重用高
  TransactionManager
    JDBCTransactionFactory和JTATransactionFactroy不需要TransactionManager,CMTTransactionFactory必须
  isTransactionInProgress
    JDBCTransactionFactory确定执行JDBCTransaction begin方法,但没提交或回滚过视为正在进行
    JTATransactionFactroy
       通过缓存的JTATransaction.getUserTransaction状态确定
       如果找不到,通过transactionManager状态确定
       如果找不到,通过JNDI查找userTransaction状态确定
   CMTTransactionFactory
       通过transactionManager.getTransaction状态确定
factory通过org.hibernate.transaction.TransactionFactoryFactory.buildTransactionFactory确定,简单表述下
    通过hibernate.transaction.factory_class确定,如果为空,返回JDBCTransactionFactory
    否则实例化hibernate.transaction.factory_class指定类,并调用configure方法
 
 事务管理器transactionManager
  TransactionManagerLookupFactory.getTransactionManagerLookup根据hibernate.transaction.manager_lookup_class确定TransactionMangerLookup,简要介绍TransactionMangerLookup
 public TransactionManager getTransactionManager(Properties props) throws HibernateException//获取JTA 事务管理器
public String getUserTransactionName();//获取JTA UserTransaction的JNDI名称
TransactionManager实现方式可分为通过JNDI查找实例和通过实例化方式;
如WeblogicTransactionManagerLookup会在JNDI上下文中查找名称为javax.transaction.TransactionManager的事务管理器
而WebSphereTransactionManagerLookup根据webSphere服务器版本加载对应的class,查找顺序为
5.1 ->com.ibm.ws.Transaction.TransactionManagerFactory
5.0->com.ibm.ejs.jts.jta.TransactionManagerFactory
4.0->com.ibm.ejs.jts.jta.JTSXA
这些类都实现了getTransactionManager静态方法,通过java反射机制获取事务管理器
JOnASTransactionManagerLookup加载org.objectweb.jonas_tm.Current,再通过反射机制调用getTransactionManager静态方法
JOTMTransactionManagerLookup加载org.objectweb.jotm.Current
当然还提供了LocalTransactionManagerLookup,查找spring管理的JTA TransactionManager实现(通过注入LocalSessionFactoryBean的transactionManager属性。


补充
事务模型


   java事务模型可分为三类:本地事务模型, 编程事务模型, 声明事务模型
    本地事务:由资源管理器处理,比如JDBC Connection,通过设置自动提交模式是否禁用来使用事务,也就是说事务处理与Connection直接相关
    编程事务模型:JTA事务由javax.transaction包API支持,事务处理与资源使用分离开来,由事务管理器参与协调多种事务性资源,所谓编程事务是相对容器管理事务而言的,这分别于EJB中的BMP和CMP对应。编程事务由javax.transaction.UserTransaction划分事务边界也就是使用begin/commit/rollback,当需要使用挂起/回复时,还必须用到javax.transaction.TransactionManager。使用它而不用容器管理事务的场景主要包括
    客户端对远程EJB Session bean进行调用
    开启JTA容器事务比较消耗资源,所以,对业务方法可以更进一步划分粒度,在方法中的莫一段使用事务
    使用无状态会话BEAN时,当客户端发起多次调用BEAN的不同方法以完成一次事务时
    容器管理事务:EJB使用声明式事务标识改BEAN的事务处理交给容器处理,容器可以接受远程编程式开启的事务,也可以自己开启事务,最终提交或回滚事务。在bean方法内,唯一能够做的有意义的事是:捕捉检查时异常,设置rollbackOnly
    


简要介绍下JTA API
  javax.transaction.Status JTA事务状态,常用状态为ACTIVE,MARKED_ROLLBACK,ROLLBACKED
  javax.transaction.Synchronization 定义了事务提交之前和提交或回滚之后执行的回调方法,这些方法一般用于清理资源,比如Session,Connection
  javax.transaction.Transaction 定义了操作全:事务提交,回滚,绑定或解绑资源事务与资源,获取状态,设置回滚,同步
  javax.transaction.TransactionManager定义了事务的所有动作,一般由应用服务器采用jts实现。也有开源实现,如JOTM.图中可以了解事务管理器与XAResource交互,并且必须提供有XADatasource的数据源
  javax.transaction.TransactionSynchronizationRegistry定义了同步,JTA1.1规范新增接口。javax.transaction.UserTransaction提供给应用客户端化分事务边界的方法
  javax.transaction.xa.XAResource定义了资源管理器与事务管理器的通信
  javax.transaction.xa.Xid定义了资源事务关联的唯一标识,就好比树的枝干,每个资源管理器做的事就对应一条枝干的标识,而所有的枝干都长在一个树上象征着在每个资源管理器上做的事就对应着整颗树。Xid中包括全局事务格式,标识,分支标识。
  
 

org.hibernate.Transaction统一了各种事务的具体实现
JDBCTransaction
JTATransaction
CMTTransaction(事务托管给应用服务器完成)
三者都认为一个session只能允许同一时刻只能由一个未提交事务,实现中大量代码主要体现在事务提交前前后后的同步问题,我们将同步分为本地同步和JTA同步,之所以分开讨论,是因为这两种同步不能同时存在以上三种之一实现中。
如果条件flushBeforeCompletionEnabled||autoCloseSessionEnabled||connectionReleaseMode ==ConnectionReleaseMode.AFTER_TRANSACTION,即事务完成之前是否flush session,事务完成之后事务自动关闭 session,连接释放是否在提交事务之后 不为真,那么认为本地同步;
如果为真,则进行如下判断
   如果采用的实现类是JBCTransaction或者TransactionManager没找到或者事务已经完成(提交或回滚,未激活等)或事务被标识为回滚,则为本地同步
   否则,为JTA同步。
JDBCTransaction中
   如果为本地同步并且flushmode !=Flushmode.Never则刷新session
   如果为本地同步,则执行org.hibernate.jdbc.JDBCContext中的beforeTransactionCompletion和afterTransactionCompletion,同时执行synchronizations集合中的各个同步类(都是javax.transaction.Synchronization实现)
JTATransaction中
   如果不是JTA同步,则认为是本地同步
   如果是JTA同步,则同步方法的执行又JTA实现自动完成,hibernate不干预
   如果是本地同步或!flushBeforeCompletionEnabled并且flushModel!=flushModel.Never,则刷新session
   如果是本地同步并且JTA事务是通过Transaction begin启动,则执行beforeTransactionCompletion
   如果JTA不是通过Transaction begin启动,则Transaction commit并不会真正触发提交
   如果是本地同步,则执行afterTransactionCompletion
CMTTransaction中
   如果不是JTA同步,Transaction begin抛出异常
   如果是JTA同步并且!flushBeforeCompletionEnabled并且flushModel!=flushModel.Never,则刷新缓存
三种实现的总结:
   JDBCTransaction只会执行本地同步
    它通过java.sql.Connection实现,并会执行JdbcContext.beforeTransactionCompletion和afterTransactionCompletion
    JTATransaction既可以进行JTA同步,也可进行本地同步;
     它通过userTransaction实现,
但在调用Transaction begin方法时会调用registerSynchronizationIfPossible而此时如果找到事务管理器,并且事务是激活的会在事务注册同步org.hibernate.transaction.CacheSynchronization,间接调用调用JdbcContext.beforeTransactionCompletion和afterTransactionCompletion
否则是本地同步。事务允许通过userTransaction.begin开始,如果不是调用Transaction begin开启事务的,那自然就不会调用JdbcContext.beforeTransactionCompletion。如果是本地同步的话,还可以调用jdbcContext.afterTransactionCompletion
    CMTTransaction不会进行实质性的事务开始,提交,回滚,超时,只设置回滚标志,当调用Transaction begin方法时会调用registerSynchronizationIfPossible而此时如果找到事务管理器会在事务上注册同步org.hibernate.transaction.CacheSynchronization,间接调用调用JdbcContext.beforeTransactionCompletion和afterTransactionCompletion
除了同步,必须关注回滚处理
  JDBCTransaction 必须调用begin开始事务,负责提交和回滚
  JTATransaction  调用begin,可能参与已经开启的事务。所以,如果只是参与性的,不能够提交,不能够回滚,只能设置rollbackOnly
  CMTTransaction  不能开启事务,提交事务,只能够设置rollbackOnly



Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐