/**
* {@link Transaction} that makes use of the JDBC commit and rollback facilities directly.
* It relies on the connection retrieved from the dataSource to
* manage the scope of the transaction.
* Delays connection retrieval until getConnection() is called.
* Ignores commit or rollback requests when autocommit is on.
*
* @author Clinton Begin
*
* @see JdbcTransactionFactory
*/publicclassJdbcTransactionimplementsTransaction{privatestaticfinal Log log = LogFactory.getLog(JdbcTransaction.class);protected Connection connection;protected DataSource dataSource;protected TransactionIsolationLevel level;protectedboolean autoCommmit;publicJdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel,boolean desiredAutoCommit){
dataSource = ds;
level = desiredLevel;
autoCommmit = desiredAutoCommit;}publicJdbcTransaction(Connection connection){this.connection = connection;}@Overridepublic Connection getConnection()throws SQLException {if(connection == null){openConnection();}return connection;}@Overridepublicvoidcommit()throws SQLException {if(connection != null &&!connection.getAutoCommit()){if(log.isDebugEnabled()){
log.debug("Committing JDBC Connection ["+ connection +"]");}
connection.commit();}}@Overridepublicvoidrollback()throws SQLException {if(connection != null &&!connection.getAutoCommit()){if(log.isDebugEnabled()){
log.debug("Rolling back JDBC Connection ["+ connection +"]");}
connection.rollback();}}@Overridepublicvoidclose()throws SQLException {if(connection != null){resetAutoCommit();if(log.isDebugEnabled()){
log.debug("Closing JDBC Connection ["+ connection +"]");}
connection.close();}}protectedvoidsetDesiredAutoCommit(boolean desiredAutoCommit){try{if(connection.getAutoCommit()!= desiredAutoCommit){if(log.isDebugEnabled()){
log.debug("Setting autocommit to "+ desiredAutoCommit +" on JDBC Connection ["+ connection +"]");}
connection.setAutoCommit(desiredAutoCommit);}}catch(SQLException e){// Only a very poorly implemented driver would fail here,// and there's not much we can do about that.thrownewTransactionException("Error configuring AutoCommit. "+"Your driver may not support getAutoCommit() or setAutoCommit(). "+"Requested setting: "+ desiredAutoCommit +". Cause: "+ e, e);}}protectedvoidresetAutoCommit(){try{if(!connection.getAutoCommit()){// MyBatis does not call commit/rollback on a connection if just selects were performed.// Some databases start transactions with select statements// and they mandate a commit/rollback before closing the connection.// A workaround is setting the autocommit to true before closing the connection.// Sybase throws an exception here.if(log.isDebugEnabled()){
log.debug("Resetting autocommit to true on JDBC Connection ["+ connection +"]");}
connection.setAutoCommit(true);}}catch(SQLException e){if(log.isDebugEnabled()){
log.debug("Error resetting autocommit to true "+"before closing the connection. Cause: "+ e);}}}protectedvoidopenConnection()throws SQLException {if(log.isDebugEnabled()){
log.debug("Opening JDBC Connection");}
connection = dataSource.getConnection();if(level != null){
connection.setTransactionIsolation(level.getLevel());}setDesiredAutoCommit(autoCommmit);}@Overridepublic Integer getTimeout()throws SQLException {return null;}}