com.frameworkset.orm.transaction.TransactionManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bboss-persistent Show documentation
Show all versions of bboss-persistent Show documentation
bboss is a j2ee framework include aop/ioc,mvc,persistent,taglib,rpc,event ,bean-xml serializable and so on.http://www.bbossgroups.com
The newest version!
/*
* Copyright 2008 biaoping.yin
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.frameworkset.orm.transaction;
import com.frameworkset.orm.annotation.TransactionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.transaction.*;
/**
*
* Title: TransactionManager
*
* Description: 实现数据库的事务框架
*
*
* bboss workgroup
*
*
* Copyright (c) 2007
*
*
* @Date 2009-6-1 下午08:58:51
* @author biaoping.yin
* @version 1.0
*/
public class TransactionManager implements java.io.Serializable {
private static final Logger log = LoggerFactory.getLogger(TransactionManager.class);
static final ThreadLocal thread_local = new ThreadLocal();
private boolean started = false;
private boolean committed = false;
private boolean rollbacked = false;
private JDBCTransaction context_tx = null;
private JDBCTransaction suspend_tx = null;
/**
* 始终创建新事务
*/
public static final TransactionType NEW_TRANSACTION = TransactionType.NEW_TRANSACTION;
/**
* 如果没有事务创建新事务,有事务加入当前事务
*/
public static final TransactionType REQUIRED_TRANSACTION = TransactionType.REQUIRED_TRANSACTION;
/**
* 有事务就加入事务,没有不创建事务,默认情况
*/
public static final TransactionType MAYBE_TRANSACTION = TransactionType.MAYBE_TRANSACTION;
/**
* 没有事务
*/
public static final TransactionType NO_TRANSACTION = TransactionType.NO_TRANSACTION;
/**
* 读写事务
*/
public static final TransactionType RW_TRANSACTION = TransactionType.RW_TRANSACTION;
/**
* 未知事务
*/
public static final TransactionType UNKNOWN_TRANSACTION = TransactionType.UNKNOWN_TRANSACTION;
private TransactionType currenttxtype = TransactionType.REQUIRED_TRANSACTION;
private static final long serialVersionUID = -6716097342564237376L;
/**
* Starts a new transaction, and associate it with the calling thread.
*
* @throws TransactionException
*
* @throws javax.transaction.NotSupportedException
* If the calling thread is already associated with a
* transaction, and nested transactions are not supported.
* @throws javax.transaction.SystemException
* If the transaction service fails in an unexpected way.
*/
public void begin() throws TransactionException {
// if(this.committed )
// throw new TransactionException("事务已经提交");
//
// if(this.rollbacked)
// throw new TransactionException("事务已经回滚");
// if(this.started == true)
// throw new TransactionException("事务已经启动,并且事务正在执行中。");
//
// JDBCTransaction currentTx = (JDBCTransaction) thread_local.get();
//
// if (currentTx != null) {
//
// currentTx.begin();
//
// } else {
// currentTx = new JDBCTransaction(this.currenttxtype);
// thread_local.set(currentTx);
// currentTx.begin();
//
// }
// this.started = true;
begin(REQUIRED_TRANSACTION);
}
/**
* Starts a new transaction, and associate it with the calling thread.
*
* @param int
* tx_type (默认值为REQUIRED_TRANSACTION)
*
*
*
* 始终创建新事务
*
* JDBCTransaction.public static final int NEW_TRANSACTION = 0;
*
*
* 如果没有事务创建新事务,有事务加入当前事务(默认值)
*
* JDBCTransaction.public static final int REQUIRED_TRANSACTION = 2;
*
*
* 有事务就加入事务,没有不创建事务,默认情况
*
* JDBCTransaction.public static final int MAYBE_TRANSACTION = 3;
*
* 没有事务
*
* JDBCTransaction.public static final int NO_TRANSACTION = 4;
* @throws TransactionException
*
* @throws javax.transaction.NotSupportedException
* If the calling thread is already associated with a
* transaction, and nested transactions are not supported.
* @throws javax.transaction.SystemException
* If the transaction service fails in an unexpected way.
*/
public void begin(TransactionType tx_type) throws TransactionException {
if(this.committed )
throw new TransactionException("事务已经提交");
if(this.rollbacked)
throw new TransactionException("事务已经回滚");
if(this.started == true)
throw new TransactionException("事务已经启动,并且事务正在执行中。");
JDBCTransaction currentTx = (JDBCTransaction) thread_local.get();
currenttxtype = tx_type;
switch (tx_type) {
case NEW_TRANSACTION:
if(currentTx == null)
{
JDBCTransaction newTx = new JDBCTransaction(NEW_TRANSACTION);
thread_local.set(newTx);
newTx.begin();
}
else
{
this.context_tx = currentTx;
JDBCTransaction newTx = new JDBCTransaction(currentTx,NEW_TRANSACTION);
newTx.begin();
thread_local.set(newTx);
}
break;
case RW_TRANSACTION:
if (currentTx != null) {
if(currentTx.getTXType() == RW_TRANSACTION)
{
currentTx.begin();
}
else
{
throw new TransactionException("当前存在类型为["+ currentTx.getTXType() +"]的事务,与RW_TRANSACTION类型事务不兼容,无法创建RW_TRANSACTION类型事务。");
}
} else {
currentTx = new JDBCTransaction(RW_TRANSACTION);
thread_local.set(currentTx);
currentTx.begin();
}
break;
case MAYBE_TRANSACTION:
if (currentTx == null)
;
else
currentTx.begin();
break;
case REQUIRED_TRANSACTION:
if (currentTx != null )
{
if(currentTx.getTXType() != RW_TRANSACTION)
{
currentTx.begin();
}
else
{
throw new TransactionException("当前存在类型为["+ currentTx.getTXType() +"]的事务,与REQUIRED_TRANSACTION类型事务不兼容,无法创建REQUIRED_TRANSACTION类型事务。");
}
}
else
{
currentTx = new JDBCTransaction(REQUIRED_TRANSACTION);
thread_local.set(currentTx);
currentTx.begin();
}
break;
case NO_TRANSACTION:
try {
suspend_tx = suspendAll();
} catch (SystemException e) {
log.warn("",e);
// TODO Auto-generated catch block
}
break;
default:
}
started = true;
}
private void assertTX() throws RollbackException
{
if(!this.started )
throw new RollbackException("事务没有开始");
if(this.committed )
throw new RollbackException("事务已经提交");
if(this.rollbacked)
throw new RollbackException("事务已经回滚");
}
/**
* Commit the transaction associated with the calling thread.
*
* @throws javax.transaction.RollbackException
* If the transaction was marked for rollback only, the
* transaction is rolled back and this exception is thrown.
* @throws IllegalStateException
* If the calling thread is not associated with a transaction.
* @throws javax.transaction.SystemException
* If the transaction service fails in an unexpected way.
* @throws javax.transaction.HeuristicMixedException
* If a heuristic decision was made and some some parts of the
* transaction have been committed while other parts have been
* rolled back.
* @throws javax.transaction.HeuristicRollbackException
* If a heuristic decision to roll back the transaction was
* made.
* @throws SecurityException
* If the caller is not allowed to commit this transaction.
*/
public void commit() throws RollbackException {
assertTX() ;
JDBCTransaction tx = getTransaction();
try
{
if(this.currenttxtype == NO_TRANSACTION)
{
try {
this.resume(this.suspend_tx);
} catch (InvalidTransactionException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalStateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SystemException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
this.committed = true;
return;
}
int status;
if (tx == null)
{
//added by biaoping.yin on 2008.09.02
if(this.currenttxtype == MAYBE_TRANSACTION)
{
this.committed = true;
return ;
}
//added end
throw new IllegalStateException(
"thread not associated with transaction");
}
if(this.context_tx != null)
{
if(context_tx == tx)
return;
}
status = tx.getStatus();
if (status == Status.STATUS_MARKED_ROLLBACK)
{
try
{
log.debug("Commit execute rolling back action.");
//如果事务被标识为回滚,则直接回滚事务,提交过程转入回滚过程
this.rollback();
this.rollbacked = true;
return ;
}
catch(Exception e)
{
this.rollbacked = true;
}
}
else
{
try {
tx.commit();
} catch (SecurityException e) {
try
{
this.rollback();
this.rollbacked = true;
}
catch(Exception ei)
{
this.rollbacked = true;
}
throw new RollbackException(e.getMessage());
} catch (IllegalStateException e) {
try
{
this.rollback();
this.rollbacked = true;
}
catch(Exception ei)
{
this.rollbacked = true;
}
throw new RollbackException(e.getMessage());
} catch (RollbackException e) {
try
{
this.rollback();
this.rollbacked = true;
}
catch(Exception ei)
{
this.rollbacked = true;
}
throw e;
} catch (HeuristicMixedException e) {
try
{
this.rollback();
this.rollbacked = true;
}
catch(Exception ei)
{
this.rollbacked = true;
}
throw new RollbackException(e.getMessage());
} catch (HeuristicRollbackException e) {
try
{
this.rollback();
this.rollbacked = true;
}
catch(Exception ei)
{
this.rollbacked = true;
}
throw new RollbackException(e.getMessage());
} catch (SystemException e) {
try
{
this.rollback();
this.rollbacked = true;
}
catch(Exception ei)
{
this.rollbacked = true;
}
throw new RollbackException(e.getMessage());
}
}
}
finally {
// if (tx.wasCommitted() || flag || rollbacked) {
// if (tx.wasCommitted() || tx.wasRolledBack()) {
if (tx != null && tx.wasCommitted() ) {
if(this.context_tx == null)
{
setTransaction(null);
}
else
{
this.setTransaction(context_tx);
//this.context_tx = null;
}
}
this.committed = true;
}
}
/**
* Rolls back the transaction associated with the calling thread.
*
* @throws IllegalStateException
* If the transaction is in a state where it cannot be rolled
* back. This could be because the calling thread is not
* associated with a transaction, or because it is in the
* {@link javax.transaction.Status#STATUS_PREPARED prepared state}.
* @throws SecurityException
* If the caller is not allowed to roll back this transaction.
* @throws javax.transaction.SystemException
* If the transaction service fails in an unexpected way.
*/
public void rollback() throws RollbackException {
_rollback(true);
}
private void _rollback(boolean check) throws RollbackException {
if(check)
assertTX() ;
if(this.currenttxtype == NO_TRANSACTION)
{
try {
this.resume(this.suspend_tx);
} catch (InvalidTransactionException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalStateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SystemException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
this.rollbacked = true;
return;
}
JDBCTransaction tx = getTransaction();
if (tx == null)
{
//added by biaoping.yin on 2008.09.02
if(this.currenttxtype == MAYBE_TRANSACTION)
{
this.rollbacked = true;
return;
}
//added end
throw new IllegalStateException(
"no transaction associated with thread or tx has been commited or rollbacked.");
}
if(this.context_tx != null)
{
if(context_tx == tx) //该条件是否会成立呢
{
this.rollbacked = true;
return;
}
}
try {
tx.rollback();
} catch (IllegalStateException e) {
log.warn("",e);
} catch (SystemException e) {
log.warn("",e);
} catch (Exception e) {
log.warn("",e);
} finally {
this.rollbacked = true;
if(tx != null && tx.wasRolledBack() )
{
if(this.context_tx == null)
{
setTransaction(null);
}
else
{
this.setTransaction(this.context_tx);
// this.context_tx = null;
}
}
}
}
// /**
// * Mark the transaction associated with the calling thread for rollback
// * only.
// *
// * @throws IllegalStateException
// * If the transaction is in a state where it cannot be rolled
// * back. This could be because the calling thread is not
// * associated with a transaction, or because it is in the
// * {@link javax.transaction.Status#STATUS_PREPARED prepared state}.
// * @throws javax.transaction.SystemException
// * If the transaction service fails in an unexpected way.
// */
// public void setRollbackOnly() throws IllegalStateException, SystemException {
//
// JDBCTransaction tx = getTransaction();
// if (tx == null)
// throw new IllegalStateException(
// "no transaction associated with calling thread");
// tx.setRollbackOnly();
// }
/**
* Get the status of the transaction associated with the calling thread.
*
* @return The status of the transaction. This is one of the
* {@link javax.transaction.Status} constants. If no transaction is
* associated with the calling thread,
* {@link javax.transaction.Status#STATUS_NO_TRANSACTION} is
* returned.
* @throws javax.transaction.SystemException
* If the transaction service fails in an unexpected way.
*/
public int getStatus() {
JDBCTransaction tx = getTransaction();
return tx != null ? tx.getStatus() : Status.STATUS_NO_TRANSACTION;
}
/**
* Get the transaction associated with the calling thread.
*
* @return The transaction associated with the calling thread, or
* null
if the calling thread is not associated with
* a transaction.
* @throws javax.transaction.SystemException
* If the transaction service fails in an unexpected way.
*/
public static JDBCTransaction getTransaction() {
JDBCTransaction tx = (JDBCTransaction) thread_local.get();
return tx;
}
/**
* Change the transaction timeout for transactions started by the calling
* thread with the {@link #begin()} method.
*
* @param seconds
* The new timeout value, in seconds. If this parameter is
* 0
, the timeout value is reset to the default
* value.
* @throws javax.transaction.SystemException
* If the transaction service fails in an unexpected way.
*/
public void setTransactionTimeout(int seconds) throws SystemException {
throw new SystemException("not supported");
}
/**
* Suspend the association the calling thread has to a transaction, and
* return the suspended transaction. When returning from this method, the
* calling thread is no longer associated with a transaction.
*
* @return The transaction that the calling thread was associated with, or
* null
if the calling thread was not associated with
* a transaction.
* @throws javax.transaction.SystemException
* If the transaction service fails in an unexpected way.
*/
public JDBCTransaction suspend() throws SystemException {
JDBCTransaction retval = getTransaction();
if(this.context_tx != null)
{
setTransaction(context_tx);
}
else
{
setTransaction(null);
}
return retval;
}
/**
* Suspend the association the calling thread has to a transaction, and
* return the suspended transaction. When returning from this method, the
* calling thread is no longer associated with a transaction.
*
* @return The transaction that the calling thread was associated with, or
* null
if the calling thread was not associated with
* a transaction.
* @throws javax.transaction.SystemException
* If the transaction service fails in an unexpected way.
*/
public JDBCTransaction suspendAll() throws SystemException {
JDBCTransaction retval = getTransaction();
setTransaction(null);
return retval;
}
/**
* Resume the association of the calling thread with the given transaction.
*
* @param tx
* The transaction to be associated with the calling thread.
* @throws javax.transaction.InvalidTransactionException
* If the argument does not represent a valid transaction.
* @throws IllegalStateException
* If the calling thread is already associated with a
* transaction.
* @throws javax.transaction.SystemException
* If the transaction service fails in an unexpected way.
*/
public void resume(JDBCTransaction tx) throws InvalidTransactionException,
IllegalStateException, SystemException {
setTransaction(tx);
}
/**
* Just used for unit tests
*
* @param tx
*/
protected void setTransaction(JDBCTransaction tx) {
thread_local.set(tx);
}
/**
* 如果成功销毁事务,则返回true
* 如果没有需要销毁的事务则返回false
* @return boolean
*/
public static boolean destroyTransaction()
{
JDBCTransaction tx = getTransaction();
if(tx != null)
{
tx.printStackTrace();
try {
tx.rollback();
} catch (IllegalStateException e) {
log.warn("",e);
} catch (SystemException e) {
log.warn("",e);
}
thread_local.set(null);
return true;
}
return false;
}
/**
* 获取当前事务的类型
* @return
*/
public TransactionType getCurrenttxtype() {
return this.currenttxtype;
}
/**
* 获取当前事务的类型名称
* @return
*/
public String getCurrenttxtypeName() {
switch(currenttxtype)
{
case NEW_TRANSACTION:
return "NEW_TRANSACTION";
case REQUIRED_TRANSACTION:
return "REQUIRED_TRANSACTION";
case MAYBE_TRANSACTION:
return "MAYBE_TRANSACTION";
case NO_TRANSACTION:
return "NO_TRANSACTION";
case RW_TRANSACTION:
return "RW_TRANSACTION";
default:
return "UNKNOWN_TRANSACTION";
}
}
/**
* 在final方法中调用,用来在出现异常时对事务资源进行回收,首先对事务进行回滚,
* 然后回收资源,如果事务已经提交和回滚,则不做任何操作
*/
public void release()
{
if(!this.started )
// throw new RollbackException("事务没有开始");
return ;
if(this.committed )
// throw new RollbackException("事务已经提交");
return ;
if(this.rollbacked)
// throw new RollbackException("事务已经回滚");
return;
try {
log.debug("Warnning:Detected uncommit Transaction,force rollbacked this transaction by system.",new Exception());
this._rollback(false);
} catch (Throwable e) {
// e.printStackTrace();
}
}
/**
* 在final方法中调用,用来在出现异常时对事务资源进行回收,首先对事务进行回滚,
* 然后回收资源,如果事务已经提交和回滚,则不做任何操作
*/
public void releasenolog()
{
if(!this.started )
// throw new RollbackException("事务没有开始");
return ;
if(this.committed )
// throw new RollbackException("事务已经提交");
return ;
if(this.rollbacked)
// throw new RollbackException("事务已经回滚");
return;
try {
// log.debug("Warnning:Detected uncommit Transaction,force rollbacked this transaction by system.",new Exception());
this._rollback(false);
} catch (Throwable e) {
// e.printStackTrace();
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy