MyBatis源码之事务模块
MyBatis 对数据库中的事务进行了抽象,其自身提供了相应的事务接口和简单实现 。在很多场景中,MyBatis 会与 Spring 框架集成,并由 Spring 框架管理事务 。主要还是看如何与spring集成
1. Transaction
事务接口, 所在包: org.apache.ibatis.transaction.Transaction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 public interface Transaction { Connection getConnection () throws SQLException; void commit () throws SQLException; void rollback () throws SQLException; void close () throws SQLException; Integer getTimeout () throws SQLException; }
1.1 JdbcTransaction
实现 Transaction 接口,基于 JDBC 的事务实现类, 所在包: org.apache.ibatis.transaction.jdbc.JdbcTransaction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 public class JdbcTransaction implements Transaction { private static final Log log = LogFactory.getLog(JdbcTransaction.class); protected Connection connection; protected DataSource dataSource; protected TransactionIsolationLevel level; protected boolean autoCommit; protected boolean skipSetAutoCommitOnClose; public JdbcTransaction (DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) { this (ds, desiredLevel, desiredAutoCommit, false ); } public JdbcTransaction (DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit, boolean skipSetAutoCommitOnClose) { dataSource = ds; level = desiredLevel; autoCommit = desiredAutoCommit; this .skipSetAutoCommitOnClose = skipSetAutoCommitOnClose; } public JdbcTransaction (Connection connection) { this .connection = connection; } @Override public Connection getConnection () throws SQLException { if (connection == null ) { openConnection(); } return connection; } @Override public void commit () throws SQLException { if (connection != null && !connection.getAutoCommit()) { if (log.isDebugEnabled()) { log.debug("Committing JDBC Connection [" + connection + "]" ); } connection.commit(); } } @Override public void rollback () throws SQLException { if (connection != null && !connection.getAutoCommit()) { if (log.isDebugEnabled()) { log.debug("Rolling back JDBC Connection [" + connection + "]" ); } connection.rollback(); } } @Override public void close () throws SQLException { if (connection != null ) { resetAutoCommit(); if (log.isDebugEnabled()) { log.debug("Closing JDBC Connection [" + connection + "]" ); } connection.close(); } } protected void setDesiredAutoCommit (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) { throw new TransactionException ( "Error configuring AutoCommit. " + "Your driver may not support getAutoCommit() or setAutoCommit(). " + "Requested setting: " + desiredAutoCommit + ". Cause: " + e, e); } } protected void resetAutoCommit () { try { if (!skipSetAutoCommitOnClose && !connection.getAutoCommit()) { 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); } } } protected void openConnection () throws SQLException { if (log.isDebugEnabled()) { log.debug("Opening JDBC Connection" ); } connection = dataSource.getConnection(); if (level != null ) { connection.setTransactionIsolation(level.getLevel()); } setDesiredAutoCommit(autoCommit); } @Override public Integer getTimeout () throws SQLException { return null ; } }
1.2 ManagedTransaction (一般都使用SpringManagedTransaction)
实现 Transaction 接口,基于容器管理的事务实现类, 所在包: org.apache.ibatis.transaction.managed.ManagedTransaction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 public class ManagedTransaction implements Transaction { private static final Log log = LogFactory.getLog(ManagedTransaction.class); private DataSource dataSource; private TransactionIsolationLevel level; private Connection connection; private final boolean closeConnection; public ManagedTransaction (Connection connection, boolean closeConnection) { this .connection = connection; this .closeConnection = closeConnection; } public ManagedTransaction (DataSource ds, TransactionIsolationLevel level, boolean closeConnection) { this .dataSource = ds; this .level = level; this .closeConnection = closeConnection; } @Override public Connection getConnection () throws SQLException { if (this .connection == null ) { openConnection(); } return this .connection; } @Override public void commit () throws SQLException { } @Override public void rollback () throws SQLException { } @Override public void close () throws SQLException { if (this .closeConnection && this .connection != null ) { if (log.isDebugEnabled()) { log.debug("Closing JDBC Connection [" + this .connection + "]" ); } this .connection.close(); } } protected void openConnection () throws SQLException { if (log.isDebugEnabled()) { log.debug("Opening JDBC Connection" ); } this .connection = this .dataSource.getConnection(); if (this .level != null ) { this .connection.setTransactionIsolation(this .level.getLevel()); } } @Override public Integer getTimeout () throws SQLException { return null ; } }
2 TransactionFactory
Transaction 工厂接口, 所在包: org.apache.ibatis.transaction.TransactionFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public interface TransactionFactory { default void setProperties (Properties props) { } Transaction newTransaction (Connection conn) ; Transaction newTransaction (DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) ; }
2.1 JdbcTransactionFactory
实现 TransactionFactory 接口,JdbcTransaction 工厂实现类, 所在包: org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class JdbcTransactionFactory implements TransactionFactory { private boolean skipSetAutoCommitOnClose; @Override public void setProperties (Properties props) { if (props == null ) { return ; } String value = props.getProperty("skipSetAutoCommitOnClose" ); if (value != null ) { skipSetAutoCommitOnClose = Boolean.parseBoolean(value); } } @Override public Transaction newTransaction (Connection conn) { return new JdbcTransaction (conn); } @Override public Transaction newTransaction (DataSource ds, TransactionIsolationLevel level, boolean autoCommit) { return new JdbcTransaction (ds, level, autoCommit, skipSetAutoCommitOnClose); } }
2.2 ManagedTransactionFactory
实现 TransactionFactory 接口,ManagedTransaction 工厂实现类, 所在包: org.apache.ibatis.transaction.managed.ManagedTransactionFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class ManagedTransactionFactory implements TransactionFactory { private boolean closeConnection = true ; @Override public void setProperties (Properties props) { if (props != null ) { String closeConnectionProperty = props.getProperty("closeConnection" ); if (closeConnectionProperty != null ) { closeConnection = Boolean.parseBoolean(closeConnectionProperty); } } } @Override public Transaction newTransaction (Connection conn) { return new ManagedTransaction (conn, closeConnection); } @Override public Transaction newTransaction (DataSource ds, TransactionIsolationLevel level, boolean autoCommit) { return new ManagedTransaction (ds, level, closeConnection); } }