📄 isolater.java
字号:
package org.hibernate.engine.transaction;
import org.hibernate.HibernateException;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.engine.SessionImplementor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Class which provides the isolation semantics required by
* an {@link IsolatedWork}.
*
* @author Steve Ebersole
*/
public class Isolater {
private static final Log log = LogFactory.getLog( Isolater.class );
/**
* The exposed service of this class. Ensures that all work actually
* performed by the given work will occur on a seperate transaction.
*
* @param work The work to be performed.
* @param session The session from which this request is originating.
* @throws HibernateException
*/
public static void doIsolatedWork(IsolatedWork work, SessionImplementor session) throws HibernateException {
boolean isJta = session.getFactory().getTransactionManager() != null;
if ( isJta ) {
new JtaDelegate( session ).delegateWork( work );
}
else {
new JdbcDelegate( session ).delegateWork( work );
}
}
// should be ok performance-wise to generate new delegate instances for each
// request since these are locally stack-scoped. Besides, it makes the code
// much easier to read than the old TransactionHelper stuff...
private static interface Delegate {
public void delegateWork(IsolatedWork work) throws HibernateException;
}
/**
* An isolation delegate for JTA-based transactions. Essentially susepnds
* any current transaction, does the work in a new transaction, and then
* resumes the initial transaction (if there was one).
*/
public static class JtaDelegate implements Delegate {
private final SessionImplementor session;
public JtaDelegate(SessionImplementor session) {
this.session = session;
}
public void delegateWork(IsolatedWork work) throws HibernateException {
TransactionManager transactionManager = session.getFactory().getTransactionManager();
Transaction surroundingTransaction = null;
Connection connection = null;
boolean caughtException = false;
try {
// First we need to suspend any current JTA transaction and obtain
// a JDBC connection
surroundingTransaction = transactionManager.suspend();
if ( log.isDebugEnabled() ) {
log.debug( "surrounding JTA transaction suspended [" + surroundingTransaction + "]" );
}
transactionManager.begin();
connection = session.getBatcher().openConnection();
// perform the actual work
work.doWork( connection );
// if everything went ok, commit the transaction and close the obtained
// connection handle...
session.getBatcher().closeConnection( connection );
transactionManager.commit();
}
catch( Throwable t ) {
// at some point the processing went bad, so we need to:
// 1) make sure the connection handle gets released
// 2) try to cleanup the JTA context as much as possible
caughtException = true;
try {
if ( connection != null && !connection.isClosed() ) {
session.getBatcher().closeConnection( connection );
}
}
catch( Throwable ignore ) {
log.trace( "unable to release connection on exception [" + ignore + "]" );
}
try {
transactionManager.rollback();
}
catch( Throwable ignore ) {
log.trace( "unable to rollback new transaction on exception [" + ignore + "]" );
}
// finally handle the exception
if ( t instanceof HibernateException ) {
throw ( HibernateException ) t;
}
else {
throw new HibernateException( "error performing isolated work", t );
}
}
finally {
if ( surroundingTransaction != null ) {
try {
transactionManager.resume( surroundingTransaction );
if ( log.isDebugEnabled() ) {
log.debug( "surrounding JTA transaction resumed [" + surroundingTransaction + "]" );
}
}
catch( Throwable t ) {
if ( !caughtException ) {
new HibernateException( "unable to resume previously suspended transaction", t );
}
}
}
}
}
}
/**
* An isolation delegate for JDBC-based transactions. Basically just
* grabs a new connection and does the work on that.
*/
public static class JdbcDelegate implements Delegate {
private final SessionImplementor session;
public JdbcDelegate(SessionImplementor session) {
this.session = session;
}
public void delegateWork(IsolatedWork work) throws HibernateException {
Connection connection = null;
boolean wasAutoCommit = false;
try {
connection = session.getBatcher().openConnection();
if ( connection.getAutoCommit() ) {
wasAutoCommit = true;
connection.setAutoCommit( false );
}
work.doWork( connection );
connection.commit();
}
catch( Throwable t ) {
try {
if ( connection!= null && !connection.isClosed() ) {
connection.rollback();
}
}
catch( Throwable ignore ) {
log.trace( "unable to release connection on exception [" + ignore + "]" );
}
if ( t instanceof HibernateException ) {
throw ( HibernateException ) t;
}
else if ( t instanceof SQLException ) {
throw JDBCExceptionHelper.convert(
session.getFactory().getSQLExceptionConverter(),
( SQLException ) t,
"error performing isolated work"
);
}
else {
throw new HibernateException( "error performing isolated work", t );
}
}
finally {
if ( wasAutoCommit ) {
try {
connection.setAutoCommit( true );
}
catch( Throwable ignore ) {
log.trace( "was unable to reset connection back to auto-commit" );
}
session.getBatcher().closeConnection( connection );
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -