Brief introduction to the affairs management of MyBatis
MyBatis's transaction management is divided into two kinds of jdbctransaction. Managedtransaction.
The jdbctransaction is only a wrapper for the database connection connection, an internal management database transaction, or a transaction operation method called Connection commit, rollback, etc. Managedtransaction is more direct, nothing is done. Direct transactions to external container management.
MyBatis transaction Management related class structure diagram
class overview:
Class UML diagram (typical simple Factory mode to create transaction):
- Transaction interface for encapsulating transaction management methods
- Transactionfactory Abstract Transaction Factory production method
- Jdbctransactionfactory implements Transactionfactory for the production of Jdbctransaction factory class
- Managedtransactionfactory implements Transactionfactory for the production of Managedtransaction factory class
- Jdbctransaction implementation of transaction, just a layer of transaction packaging, the actual call database connection connection Transaction management method
- Managedtransaction implementation transaction does not do any transactional processing of database connections, by external container management
Source Code Transaction Transaction Configuration
The configuration for transactions in MyBatis is <transaction type="xx"/>
specified by. Configuration such as the following:
<environments Default="Development"> <environment ID="Development"> <transactionmanager type="JDBC"/> <dataSource type="Pooled"> < property name="Driver" value="${jdbc.driverclassname}" /> < property name="url" value="${jdbc.url}"/> < property name="username" value="${jdbc.username}"/> < property name="password" value="${jdbc.password}" /> </dataSource> </Environment> </environments>
- When type is "JDBC", use Jdbctransaction to manage transactions.
When type is "managed", use Managedtransaction to manage transactions (that is, by external container management)
MyBatis in-depth initialization process to know how to parse the configuration file, the analysis of the transaction:
private void environmentsElement(XNode context) throws Exception { //仅仅关注事务部分... TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager")); ... }
private transactionfactory Span class= "Hljs-title" >transactionmanagerelement (xnode context) throws Exception {if (context! = null ) {String type = Context.getstringattribute ( "type" ); Properties props = Context.getchildrenasproperties (); Transactionfactory factory = (transactionfactory) resolveclass (type). newinstance (); Factory.setproperties (props); return factory; } throw new builderexception (" Environment declaration requires a transactionfactory. ");}
typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class); typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
- The key is to infer what transactionfactory to instantiate based on type types
- We already know the way MyBatis two transactions are configured, the JDBC type of transactions used here
- The previous analysis of the DataSource instantiation process is about the basis of datasource type to obtain what kind of factory, the principle of the same
- Get Transactionfactory Implementation class Jdbctransactionfactory by typealiasregistry based on type= ' JDBC '
The key is what the Jdbctransactionfactory does with newinstance () when using the non-participating constructors
Public class jdbctransactionfactory implements transactionfactory { Public void setproperties(Properties props) { } PublicTransactionnewtransaction(Connection conn) {return NewJdbctransaction (conn); } PublicTransactionnewtransaction(DataSource ds, Transactionisolationlevel level,BooleanAutocommit) {return NewJdbctransaction (DS, Level, autocommit); }}
- Jdbctransactionfactory default no-participation method is called
- SetProperties did not do whatever substantive treatment
- Control Managedtransactionfactory no longer post code
Here's how to get a database connection with transactional attributes
Jdbctransaction:
publicnewTransaction(Connection conn) { returnnew JdbcTransaction(conn); }
Managedtransaction:
publicnewTransaction(Connection conn) { returnnew ManagedTransaction(conn, closeConnection); }
- Both are created by connection to create a detailed instance
Jdbctransaction:
Public class jdbctransaction implements Transaction { Private Static FinalLog log = Logfactory.getlog (Jdbctransaction.class);protectedConnection Connection;protectedDataSource DataSource;protectedTransactionisolationlevel level;protected BooleanAutocommmit; Public jdbctransaction(DataSource ds, Transactionisolationlevel desiredlevel,BooleanDesiredautocommit) {dataSource = ds; level = Desiredlevel; Autocommmit = Desiredautocommit; } Public jdbctransaction(Connection Connection) { This. Connection = connection; } PublicConnectiongetconnection()throwsSQLException {if(Connection = =NULL) {openconnection (); }returnConnection } Public void Commit()throwsSQLException {if(Connection! =NULL&&!connection.getautocommit ()) {if(Log.isdebugenabled ()) {Log.debug ("Committing JDBC Connection ["+ Connection +"]"); } connection.commit (); } } Public void rollback()throwsSQLException {if(Connection! =NULL&&!connection.getautocommit ()) {if(Log.isdebugenabled ()) {Log.debug ("rolling back JDBC Connection ["+ Connection +"]"); } connection.rollback (); } } Public void Close()throwsSQLException {if(Connection! =NULL) {resetautocommit ();if(Log.isdebugenabled ()) {Log.debug ("Closing JDBC Connection ["+ Connection +"]"); } connection.close (); } }protected void Setdesiredautocommit(BooleanDesiredautocommit) {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 does about that. Throw NewTransactionException ("Error Configuring Autocommit. "+"Your driver may not be support getautocommit () or Setautocommit ()."+"requested setting:"+ Desiredautocommit +". Cause: "+ E, E); } }protected void Resetautocommit() {Try{if(!connection.getautocommit ()) {//MyBatis does not-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) {Log.debug ("Error resetting autocommit to True"+"Before closing the connection. Cause: "+ e); } }protected void OpenConnection()throwsSQLException {if(Log.isdebugenabled ()) {Log.debug ("Opening JDBC Connection"); } connection = Datasource.getconnection ();if(Level! =NULL) {connection.settransactionisolation (Level.getlevel ()); } setdesiredautocommit (Autocommmit); }}
- From the source code, jdbctransaction How to manage the transaction, as previously said, call the DataSource transaction operation method.
- And no transaction control on select
- When you create a database connection using DataSource, the transaction isolation level of the database uses the DataSource default transaction isolation Level
- To specify the isolation level of a transaction, you must manually create the Jdbctransaction (call has a constructor)
- About the transaction isolation level is available in the supplement
Managedtransaction:
Public class managedtransaction implements Transaction { Private Static FinalLog log = Logfactory.getlog (Managedtransaction.class);PrivateDataSource DataSource;PrivateTransactionisolationlevel level;PrivateConnection Connection;Private BooleanCloseConnection; Public managedtransaction(Connection Connection,BooleanCloseConnection) { This. Connection = connection; This. CloseConnection = CloseConnection; } Public managedtransaction(DataSource ds, Transactionisolationlevel level,BooleanCloseConnection) { This. DataSource = ds; This. level = level; This. CloseConnection = CloseConnection; } PublicConnectiongetconnection()throwsSQLException {if( This. Connection = =NULL) {openconnection (); }return This. Connection; } Public void Commit()throwsSQLException {//Does Nothing} Public void rollback()throwsSQLException {//Does Nothing} Public void Close()throwsSQLException {if( This. CloseConnection && This. Connection! =NULL) {if(Log.isdebugenabled ()) {Log.debug ("Closing JDBC Connection ["+ This. Connection +"]"); } This. Connection.close (); } }protected void OpenConnection()throwsSQLException {if(Log.isdebugenabled ()) {Log.debug ("Opening JDBC Connection"); } This. Connection = This. Datasource.getconnection ();if( This. level! =NULL) { This. Connection.settransactionisolation ( This. Level.getlevel ()); } }}
- Focus on
commit()
rollback()
the method, there is no method body. Verify the previous management of the transaction
In this case, the transaction is temporarily over, and it is generally used in conjunction with spring, connecting the database, and managing the transaction to spring.
Add
Database Isolation Level:
先对不同隔离级别涉及到的名词解释:? 脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是暂时且无效的. ? 不可反复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了. ? 幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 假设 T1 再次读取同一个表, 就会多出几
A detailed isolation level definition:
READ UNCOMMITTED(读未提交数据) 同意事务读取未被其它事务提交的变更,脏读、不可反复读和幻读的问题都会出现 READ COMMITED(读已提交数据) 仅仅同意事务读取已经被其它事务提交的变更。能够避免脏读,但不可反复读和幻读问题仍然会出现 READ(可反复读) 确保事务能够多次从一个字段中读取同样的值,在这个事务持续期间,禁止其它事务对这个字段进行更新。能够避免脏读和不可反复读,但幻读的问题依旧存在 SERIALIZABLE(串行化) 确保事务能够从一个表中读取同样的行。在这个事务持续期间。禁止其它事务对该表运行插入、更新和删除操作,全部并发问题都能够避免。但性能十分低 2 种事务隔离级别:READREAD COMMITED 4READ
A lot of other content: Mybatis folder
MyBatis in-depth management of affairs