publicinterfaceTransactionDefinition{// 传播机制intPROPAGATION_REQUIRED=0;intPROPAGATION_SUPPORTS=1;intPROPAGATION_MANDATORY=2;intPROPAGATION_REQUIRES_NEW=3;intPROPAGATION_NOT_SUPPORTED=4;intPROPAGATION_NEVER=5;intPROPAGATION_NESTED=6;// 隔离级别intISOLATION_DEFAULT=-1;intISOLATION_READ_UNCOMMITTED=1;// same as java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;intISOLATION_READ_COMMITTED=2;// same as java.sql.Connection.TRANSACTION_READ_COMMITTED;intISOLATION_REPEATABLE_READ=4;// same as java.sql.Connection.TRANSACTION_REPEATABLE_READ;intISOLATION_SERIALIZABLE=8;// same as java.sql.Connection.TRANSACTION_SERIALIZABLE;intTIMEOUT_DEFAULT=-1;}
protectedTransactionAttributeparseTransactionAnnotation(AnnotationAttributesattributes){RuleBasedTransactionAttributerbta=newRuleBasedTransactionAttribute();Propagationpropagation=attributes.getEnum("propagation");rbta.setPropagationBehavior(propagation.value());Isolationisolation=attributes.getEnum("isolation");rbta.setIsolationLevel(isolation.value());rbta.setTimeout(attributes.getNumber("timeout").intValue());StringtimeoutString=attributes.getString("timeoutString");Assert.isTrue(!StringUtils.hasText(timeoutString)||rbta.getTimeout()<0,"Specify 'timeout' or 'timeoutString', not both");rbta.setTimeoutString(timeoutString);rbta.setReadOnly(attributes.getBoolean("readOnly"));rbta.setQualifier(attributes.getString("value"));rbta.setLabels(Arrays.asList(attributes.getStringArray("label")));List<RollbackRuleAttribute>rollbackRules=newArrayList<>();for(Class<?>rbRule:attributes.getClassArray("rollbackFor")){rollbackRules.add(newRollbackRuleAttribute(rbRule));}for(StringrbRule:attributes.getStringArray("rollbackForClassName")){rollbackRules.add(newRollbackRuleAttribute(rbRule));}for(Class<?>rbRule:attributes.getClassArray("noRollbackFor")){rollbackRules.add(newNoRollbackRuleAttribute(rbRule));}for(StringrbRule:attributes.getStringArray("noRollbackForClassName")){rollbackRules.add(newNoRollbackRuleAttribute(rbRule));}rbta.setRollbackRules(rollbackRules);returnrbta;}
3. Spring事务处理逻辑
3.1. TransactionInterceptor
1
2
3
4
@Transactionalpublicvoidinsert(){jdbcTemplate.execute("insert into user(name,sex,age) values('test','男',18)");}
protectedObjectinvokeWithinTransaction(Methodmethod,@NullableClass<?>targetClass,finalInvocationCallbackinvocation)throwsThrowable{// TransactionAttribute就是@Transactional中的配置TransactionAttributeSourcetas=getTransactionAttributeSource();// 获取@Transactional注解中的属性值finalTransactionAttributetxAttr=(tas!=null?tas.getTransactionAttribute(method,targetClass):null);// 返回Spring容器中类型为TransactionManager的Bean对象finalTransactionManagertm=determineTransactionManager(txAttr);// ReactiveTransactionManager用得少,并且它只是执行方式是响应式的,原理流程和普通的是一样的// ,..// 把tm强制转换成PlatformTransactionManager, 所以我们在定义时得定义PlatformTransactionManager类型PlatformTransactionManagerptm=asPlatformTransactionManager(tm);// joinpoint的唯一标识, 就是当前在执行方法的名字finalStringjoinpointIdentification=methodIdentification(method,targetClass,txAttr);// CallbackPreferringPlatformTransactionManager表示有回调功能的PlatformTransactionManagerif(txAttr==null||!(ptminstanceofCallbackPreferringPlatformTransactionManager)){// Standard transaction demarcation with getTransaction and commit/rollback calls.// ☆ ->// 如果有必要就创建事务,这里就涉及到事务传播机制的实现了// TransactionInfo表示一个逻辑事务,比如两个逻辑事务属于同一个物理事务TransactionInfotxInfo=createTransactionIfNecessary(ptm,txAttr,joinpointIdentification);ObjectretVal;try{// This is an around advice: Invoke the next interceptor in the chain.// This will normally result in a target object being invoked.// 执行下一个Interceptor或被代理对象中的方法retVal=invocation.proceedWithInvocation();// test()}catch(Throwableex){// target invocation exception// 抛异常了, 回滚事务completeTransactionAfterThrowing(txInfo,ex);throwex;}finally{cleanupTransactionInfo(txInfo);}if(retVal!=null&&vavrPresent&&VavrDelegate.isVavrTry(retVal)){// Set rollback-only in case of Vavr failure matching our rollback rules...TransactionStatusstatus=txInfo.getTransactionStatus();if(status!=null&&txAttr!=null){retVal=VavrDelegate.evaluateTryFailure(retVal,txAttr,status);}}// 提交事务commitTransactionAfterReturning(txInfo);returnretVal;}else{// ...}}
protectedTransactionInfocreateTransactionIfNecessary(@NullablePlatformTransactionManagertm,@NullableTransactionAttributetxAttr,finalStringjoinpointIdentification){// If no name specified, apply method identification as transaction name.if(txAttr!=null&&txAttr.getName()==null){txAttr=newDelegatingTransactionAttribute(txAttr){@OverridepublicStringgetName(){returnjoinpointIdentification;}};}// 每个逻辑事务都会创建一个TransactionStatus,// 但是TransactionStatus中有一个属性代表当前逻辑事务底层的物理事务是不是新的TransactionStatusstatus=null;if(txAttr!=null){if(tm!=null){// ☆ ->// 开启事务status=tm.getTransaction(txAttr);}else{if(logger.isDebugEnabled()){logger.debug("Skipping transactional joinpoint ["+joinpointIdentification+"] because no transaction manager has been configured");}}}//returnprepareTransactionInfo(tm,txAttr,joinpointIdentification,status);}
@OverridepublicfinalTransactionStatusgetTransaction(@NullableTransactionDefinitiondefinition)throwsTransactionException{// Use defaults if no transaction definition given.TransactionDefinitiondef=(definition!=null?definition:TransactionDefinition.withDefaults());// 获取一个新的DataSourceTransactionObject对象Objecttransaction=doGetTransaction();booleandebugEnabled=logger.isDebugEnabled();// 判断是否存在一个事务if(isExistingTransaction(transaction)){// Existing transaction found -> check propagation behavior to find out how to behave.// 已经存在一个事务了returnhandleExistingTransaction(def,transaction,debugEnabled);}// 不存在事务// Check definition settings for new transaction.// 判断@Transactional(timeout=?)if(def.getTimeout()<TransactionDefinition.TIMEOUT_DEFAULT){thrownewInvalidTimeoutException("Invalid transaction timeout",def.getTimeout());}// No existing transaction found -> check propagation behavior to find out how to proceed.if(def.getPropagationBehavior()==TransactionDefinition.PROPAGATION_MANDATORY){// 如果配置的事手动开启事务 则直接抛出异常thrownewIllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");}elseif(def.getPropagationBehavior()==TransactionDefinition.PROPAGATION_REQUIRED||def.getPropagationBehavior()==TransactionDefinition.PROPAGATION_REQUIRES_NEW||def.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NESTED){// 当前的Thread中在没有事务的前提下, 上面三种传播机制是等价的// 没有事务需要挂起, 不过TransactionSynchronization有可能需要挂起// suspendedResources表示当前线程被挂起的资源持有对象(数据库连接、TransactionSynchronization)SuspendedResourcesHoldersuspendedResources=suspend(null);if(debugEnabled){logger.debug("Creating new transaction with name ["+def.getName()+"]: "+def);}try{// ☆ ->// 开启事务后, transaction中就会有数据库连接了, 并且是isTransactionActive为true的// 并返回TransactionStatus对象, 该对象保存了很多信息, 包括被挂起的资源returnstartTransaction(def,transaction,debugEnabled,suspendedResources);}catch(RuntimeException|Errorex){resume(null,suspendedResources);throwex;}}else{// Create "empty" transaction: no actual transaction, but potentially synchronization.if(def.getIsolationLevel()!=TransactionDefinition.ISOLATION_DEFAULT&&logger.isWarnEnabled()){logger.warn("Custom isolation level specified but no actual transaction initiated; isolation level will effectively be ignored: "+def);}booleannewSynchronization=(getTransactionSynchronization()==SYNCHRONIZATION_ALWAYS);returnprepareTransactionStatus(def,null,true,newSynchronization,debugEnabled,null);}}
privatestaticfinalThreadLocal<Map<Object,Object>>resources=newNamedThreadLocal<>("Transactional resources");@NullableprivatestaticObjectdoGetResource(ObjectactualKey){Map<Object,Object>map=resources.get();if(map==null){returnnull;}Objectvalue=map.get(actualKey);// Transparently remove ResourceHolder that was marked as void...if(valueinstanceofResourceHolder&&((ResourceHolder)value).isVoid()){map.remove(actualKey);// Remove entire ThreadLocal if empty...if(map.isEmpty()){resources.remove();}value=null;}returnvalue;}
privateTransactionStatushandleExistingTransaction(TransactionDefinitiondefinition,Objecttransaction,booleandebugEnabled)throwsTransactionException{// 判断当前事务的传播机制// 如果是NEVER 就直接报错if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NEVER){// 以非事务方式运行,如果当前存在事务,则抛出异常thrownewIllegalTransactionStateException("Existing transaction found for transaction marked with propagation 'never'");}if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NOT_SUPPORTED){// 以非事务方式运行,如果当前存在事务,则把当前事务挂起。if(debugEnabled){logger.debug("Suspending current transaction");}// 挂起当前事务, 不新建事务ObjectsuspendedResources=suspend(transaction);booleannewSynchronization=(getTransactionSynchronization()==SYNCHRONIZATION_ALWAYS);returnprepareTransactionStatus(definition,null,false,newSynchronization,debugEnabled,suspendedResources);}if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_REQUIRES_NEW){// 不管当前有没有事务, 都会新建一个事务if(debugEnabled){logger.debug("Suspending current transaction, creating new transaction with name ["+definition.getName()+"]");}// 先挂起当前事务SuspendedResourcesHoldersuspendedResources=suspend(transaction);try{// 开启一个新事务returnstartTransaction(definition,transaction,debugEnabled,suspendedResources);}catch(RuntimeException|ErrorbeginEx){resumeAfterBeginException(transaction,suspendedResources,beginEx);throwbeginEx;}}if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NESTED){// 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIREDif(!isNestedTransactionAllowed()){thrownewNestedTransactionNotSupportedException("Transaction manager does not allow nested transactions by default - specify 'nestedTransactionAllowed' property with value 'true'");}if(debugEnabled){logger.debug("Creating nested transaction with name ["+definition.getName()+"]");}if(useSavepointForNestedTransaction()){DefaultTransactionStatusstatus=prepareTransactionStatus(definition,transaction,false,false,debugEnabled,null);// 创建一个savepointstatus.createAndHoldSavepoint();returnstatus;}else{// Nested transaction through nested begin and commit/rollback calls.// Usually only for JTA: Spring synchronization might get activated here// in case of a pre-existing JTA transaction.returnstartTransaction(definition,transaction,debugEnabled,null);}}// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.if(debugEnabled){logger.debug("Participating in existing transaction");}if(isValidateExistingTransaction()){if(definition.getIsolationLevel()!=TransactionDefinition.ISOLATION_DEFAULT){IntegercurrentIsolationLevel=TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();if(currentIsolationLevel==null||currentIsolationLevel!=definition.getIsolationLevel()){ConstantsisoConstants=DefaultTransactionDefinition.constants;thrownewIllegalTransactionStateException("Participating transaction with definition ["+definition+"] specifies isolation level which is incompatible with existing transaction: "+(currentIsolationLevel!=null?isoConstants.toCode(currentIsolationLevel,DefaultTransactionDefinition.PREFIX_ISOLATION):"(unknown)"));}}if(!definition.isReadOnly()){if(TransactionSynchronizationManager.isCurrentTransactionReadOnly()){thrownewIllegalTransactionStateException("Participating transaction with definition ["+definition+"] is not marked as read-only but existing transaction is");}}}// 如果依然是Propagation.REQUIREDbooleannewSynchronization=(getTransactionSynchronization()!=SYNCHRONIZATION_NEVER);returnprepareTransactionStatus(definition,transaction,false,newSynchronization,debugEnabled,null);}}
protectedfinalSuspendedResourcesHoldersuspend(@NullableObjecttransaction)throwsTransactionException{// synchronizations 是一个ThreadLocal<Set<TransactionSynchronization>>// 我们可以在任何地方通过TransactionSynchronizationManager给当前线程添加TransactionSynchronization.if(TransactionSynchronizationManager.isSynchronizationActive()){// 调用TransactionSynchronization的suspend方法, 并清空和返回当前线程中所有的List<TransactionSynchronization>suspendedSynchronizations=doSuspendSynchronization();try{ObjectsuspendedResources=null;if(transaction!=null){// 挂起事务, 把transaction中的Connection清空, 并把resources中的key-value进行移除,// 并返回数据连接Connection对象suspendedResources=doSuspend(transaction);}// 获取并清空当前线程中关于TransactionSynchronizationManager的设置,// 准备开启新的事务(因为你都要挂起了, 肯定是为了新开启别的事务)Stringname=TransactionSynchronizationManager.getCurrentTransactionName();TransactionSynchronizationManager.setCurrentTransactionName(null);booleanreadOnly=TransactionSynchronizationManager.isCurrentTransactionReadOnly();TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);IntegerisolationLevel=TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);booleanwasActive=TransactionSynchronizationManager.isActualTransactionActive();TransactionSynchronizationManager.setActualTransactionActive(false);// 将当前线程中的数据库连接对象、TransactionSynchronization对象、TransactionSynchronizationManager中的设置构造成一个对象// 表示被挂起的资源持有对象,持有了当前线程中的事务对象、TransactionSynchronization对象returnnewSuspendedResourcesHolder(suspendedResources,suspendedSynchronizations,name,readOnly,isolationLevel,wasActive);}catch(RuntimeException|Errorex){// doSuspend failed - original transaction is still active...doResumeSynchronization(suspendedSynchronizations);throwex;}}elseif(transaction!=null){// Transaction active but no synchronization active.ObjectsuspendedResources=doSuspend(transaction);returnnewSuspendedResourcesHolder(suspendedResources);}else{// Neither transaction nor synchronization active.returnnull;}}
@Transactionalpublicvoidinsert(){TransactionSynchronizationManager.registerSynchronization(newTransactionSynchronization(){@Overridepublicvoidsuspend(){TransactionSynchronization.super.suspend();}@Overridepublicvoidresume(){TransactionSynchronization.super.resume();}@OverridepublicvoidbeforeCommit(booleanreadOnly){TransactionSynchronization.super.beforeCommit(readOnly);}@OverridepublicvoidafterCommit(){TransactionSynchronization.super.afterCommit();}});jdbcTemplate.execute("insert into user(name,sex,age) values('test','男',18)");}
@Overridepublicfinalvoidcommit(TransactionStatusstatus)throwsTransactionException{if(status.isCompleted()){thrownewIllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");}DefaultTransactionStatusdefStatus=(DefaultTransactionStatus)status;// 可以通过TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 来设置// 判断是否需要强制回滚if(defStatus.isLocalRollbackOnly()){if(defStatus.isDebug()){logger.debug("Transactional code has requested rollback");}processRollback(defStatus,false);return;}// 判断此事务在之前是否设置了需要回滚, 跟globalRollbackOnParticipationFailure有关if(!shouldCommitOnGlobalRollbackOnly()&&defStatus.isGlobalRollbackOnly()){if(defStatus.isDebug()){logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");}processRollback(defStatus,true);return;}processCommit(defStatus);}
privatevoidprocessCommit(DefaultTransactionStatusstatus)throwsTransactionException{try{booleanbeforeCompletionInvoked=false;try{booleanunexpectedRollback=false;// 前面说到的register进去的几个回调方法prepareForCommit(status);triggerBeforeCommit(status);triggerBeforeCompletion(status);beforeCompletionInvoked=true;if(status.hasSavepoint()){if(status.isDebug()){logger.debug("Releasing transaction savepoint");}unexpectedRollback=status.isGlobalRollbackOnly();status.releaseHeldSavepoint();}elseif(status.isNewTransaction()){if(status.isDebug()){logger.debug("Initiating transaction commit");}unexpectedRollback=status.isGlobalRollbackOnly();// ☆ ->doCommit(status);}elseif(isFailEarlyOnGlobalRollbackOnly()){unexpectedRollback=status.isGlobalRollbackOnly();}// Throw UnexpectedRollbackException if we have a global rollback-only// marker but still didn't get a corresponding exception from commit.if(unexpectedRollback){thrownewUnexpectedRollbackException("Transaction silently rolled back because it has been marked as rollback-only");}}catch(UnexpectedRollbackExceptionex){// can only be caused by doCommit// 触发回调triggerAfterCompletion(status,TransactionSynchronization.STATUS_ROLLED_BACK);throwex;}catch(TransactionExceptionex){// can only be caused by doCommitif(isRollbackOnCommitFailure()){doRollbackOnCommitException(status,ex);}else{// 触发回调triggerAfterCompletion(status,TransactionSynchronization.STATUS_UNKNOWN);}throwex;}catch(RuntimeException|Errorex){if(!beforeCompletionInvoked){// 触发回调triggerBeforeCompletion(status);}doRollbackOnCommitException(status,ex);throwex;}// Trigger afterCommit callbacks, with an exception thrown there// propagated to callers but the transaction still considered as committed.try{triggerAfterCommit(status);}finally{triggerAfterCompletion(status,TransactionSynchronization.STATUS_COMMITTED);}}finally{// 恢复被挂起的资源到当前线程中cleanupAfterCompletion(status);}}
在上面的方法中else if (status.isNewTransaction())这个分支判断了当前事务是不是我正在执行的这个方法(如userService的insert方法)新建的,如果是,那么我就可以现在提交。如果不是,有可能是传播下来的,那我现在还不能提交,需要到创建这个事务的方法中去提交。
3.7. doCommit
最关键的方法就是doCommit()方法:
DataSourceTransactionManager#doCommit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@OverrideprotectedvoiddoCommit(DefaultTransactionStatusstatus){DataSourceTransactionObjecttxObject=(DataSourceTransactionObject)status.getTransaction();Connectioncon=txObject.getConnectionHolder().getConnection();if(status.isDebug()){logger.debug("Committing JDBC transaction on Connection ["+con+"]");}try{// 提交con.commit();}catch(SQLExceptionex){throwtranslateException("JDBC commit",ex);}}
protectedvoidcompleteTransactionAfterThrowing(@NullableTransactionInfotxInfo,Throwableex){if(txInfo!=null&&txInfo.getTransactionStatus()!=null){if(logger.isTraceEnabled()){logger.trace("Completing transaction for ["+txInfo.getJoinpointIdentification()+"] after exception: "+ex);}// transactionAttribute的实现类为[RuleBasedTransactionAttribute], 父类为DefaultTransactionAttributeif(txInfo.transactionAttribute!=null&&txInfo.transactionAttribute.rollbackOn(ex)){try{txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());}catch(TransactionSystemExceptionex2){logger.error("Application exception overridden by rollback exception",ex);ex2.initApplicationException(ex);throwex2;}catch(RuntimeException|Errorex2){logger.error("Application exception overridden by rollback exception",ex);throwex2;}}else{// We don't roll back on this exception.// Will still roll back if TransactionStatus.isRollbackOnly() is true.try{txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}catch(TransactionSystemExceptionex2){logger.error("Application exception overridden by commit exception",ex);ex2.initApplicationException(ex);throwex2;}catch(RuntimeException|Errorex2){logger.error("Application exception overridden by commit exception",ex);throwex2;}}}}
publicbooleanrollbackOn(Throwableex){RollbackRuleAttributewinner=null;intdeepest=Integer.MAX_VALUE;if(this.rollbackRules!=null){// 遍历所有的RollbackRuleAttribute, 判断现在抛出的异常ex是否匹配RollbackRuleAttribute中指定的异常类型的子类或本身for(RollbackRuleAttributerule:this.rollbackRules){intdepth=rule.getDepth(ex);if(depth>=0&&depth<deepest){deepest=depth;winner=rule;}}}// User superclass behavior (rollback on unchecked) if no rule matches.if(winner==null){returnsuper.rollbackOn(ex);}// ex所匹配的RollbackRuleAttribute, 可能是NoRollbackRuleAttribute, 如果是匹配的NoRollbackRuleAttribute,// 那就表示现在这个异常ex 不用刚回滚return!(winnerinstanceofNoRollbackRuleAttribute);}
3.8. rollback
1
2
3
4
5
6
7
8
9
@Overridepublicfinalvoidrollback(TransactionStatusstatus)throwsTransactionException{if(status.isCompleted()){thrownewIllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");}DefaultTransactionStatusdefStatus=(DefaultTransactionStatus)status;processRollback(defStatus,false);}
privatevoidprocessRollback(DefaultTransactionStatusstatus,booleanunexpected){try{booleanunexpectedRollback=unexpected;try{// 回滚之前先触发下面的回调triggerBeforeCompletion(status);if(status.hasSavepoint()){// 回滚到上一个savepoint位置status.rollbackToHeldSavepoint();}elseif(status.isNewTransaction()){if(status.isDebug()){logger.debug("Initiating transaction rollback");}// ☆ ->// 如果当前执行的方法是新开的事务, 则直接回滚doRollback(status);}else{// Participating in larger transaction// 如果当前执行的方法已经有一个事务了, 而当前执行的方法抛出了异常, 则要判断整个事务到底要不要回滚, 看具体配置if(status.hasTransaction()){// 如果一个事务中有两个方法,第二个方法抛异常了,那么第二个方法就相当于执行失败需要回滚,// 如果globalRollbackOnParticipationFailure为true,那么第一个方法在没有抛异常的情况下也要回滚if(status.isLocalRollbackOnly()||isGlobalRollbackOnParticipationFailure()){if(status.isDebug()){logger.debug("Participating transaction failed - marking existing transaction as rollback-only");}// 直接将rollbackOnly设置到ConnectionHolder中去, 表示整个事务的sql都要回滚doSetRollbackOnly(status);}else{if(status.isDebug()){logger.debug("Participating transaction failed - letting transaction originator decide on rollback");}}}else{logger.debug("Should roll back transaction but cannot - no transaction available");}// Unexpected rollback only matters here if we're asked to fail earlyif(!isFailEarlyOnGlobalRollbackOnly()){unexpectedRollback=false;}}}catch(RuntimeException|Errorex){triggerAfterCompletion(status,TransactionSynchronization.STATUS_UNKNOWN);throwex;}triggerAfterCompletion(status,TransactionSynchronization.STATUS_ROLLED_BACK);// Raise UnexpectedRollbackException if we had a global rollback-only markerif(unexpectedRollback){thrownewUnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only");}}finally{cleanupAfterCompletion(status);}}
@OverrideprotectedvoiddoRollback(DefaultTransactionStatusstatus){DataSourceTransactionObjecttxObject=(DataSourceTransactionObject)status.getTransaction();Connectioncon=txObject.getConnectionHolder().getConnection();if(status.isDebug()){logger.debug("Rolling back JDBC transaction on Connection ["+con+"]");}try{con.rollback();}catch(SQLExceptionex){throwtranslateException("JDBC rollback",ex);}}