上一篇:mybatis源碼分析之Configurationjava
主要分析了構建SqlSessionFactory的過程當中配置文件的讀取.sql
此次重點分析mybatis的事務管理器數據庫
仍舊從官網給的例子着手分析,配置文件mybatis-config.xmlsession
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>
在根結點configuration下有environments和mappers兩個結點.mybatis
environments:環境,mybatis能夠配置多個環境便可以將 SQL 映射應用於多種數據庫之中.如開發,測試,生產對應不一樣的數據庫.app
mappers:映射器,提供映射文件的地址.源碼分析
在environment下的transactionManager就是如今要重點分析的對象.測試
mybatis中有兩種類型的事務管理器,JDBC和MANAGED.fetch
JDBC:直接使用了 JDBC 的提交和回滾設置,它依賴於從數據源獲得的鏈接來管理事務範圍。ui
MANAGED:不提交或回滾一個鏈接,而是讓容器來管理事務的整個生命週期。
對例子進行分析,以前分析過
String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
如今再來分析
SqlSession session = sqlSessionFactory.openSession();
DefaultSqlSessionFactory裏的openSession
public SqlSession openSession() { return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); }
openSessionFromDataSource
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { //根據配置獲取環境 final Environment environment = configuration.getEnvironment(); //構建事務工廠 final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); //經過事務工廠建立事務 tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); final Executor executor = configuration.newExecutor(tx, execType); return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
看一下各個類之間的關係
JdbcTransaction和ManagedTransaction對應事務管理器的兩種類型JDBC和MANAGED.
因爲ManagedTransaction幾乎沒作什麼,因此重點分析JdbcTransaction.
由於JdbcTransaction直接使用了 JDBC 的提交和回滾設置,它依賴於從數據源獲得的鏈接來管理事務範圍。
那麼直接來看看JDBC的事務
java.sql.Connection
/** * A constant indicating that transactions are not supported. */ int TRANSACTION_NONE = 0; /** * A constant indicating that * dirty reads, non-repeatable reads and phantom reads can occur. * This level allows a row changed by one transaction to be read * by another transaction before any changes in that row have been * committed (a "dirty read"). If any of the changes are rolled back, * the second transaction will have retrieved an invalid row. */ int TRANSACTION_READ_UNCOMMITTED = 1; /** * A constant indicating that * dirty reads are prevented; non-repeatable reads and phantom * reads can occur. This level only prohibits a transaction * from reading a row with uncommitted changes in it. */ int TRANSACTION_READ_COMMITTED = 2; /** * A constant indicating that * dirty reads and non-repeatable reads are prevented; phantom * reads can occur. This level prohibits a transaction from * reading a row with uncommitted changes in it, and it also * prohibits the situation where one transaction reads a row, * a second transaction alters the row, and the first transaction * rereads the row, getting different values the second time * (a "non-repeatable read"). */ int TRANSACTION_REPEATABLE_READ = 4; /** * A constant indicating that * dirty reads, non-repeatable reads and phantom reads are prevented. * This level includes the prohibitions in * <code>TRANSACTION_REPEATABLE_READ</code> and further prohibits the * situation where one transaction reads all rows that satisfy * a <code>WHERE</code> condition, a second transaction inserts a row that * satisfies that <code>WHERE</code> condition, and the first transaction * rereads for the same condition, retrieving the additional * "phantom" row in the second read. */ int TRANSACTION_SERIALIZABLE = 8;
事務隔離級別
TRANSACTION_NONE:不支持事務
TRANSACTION_READ_UNCOMMITTED:容許髒讀、不可重複的讀和虛讀.
TRANSACTION_READ_COMMITTED:不容許髒讀,容許不可重複的讀和虛讀.
TRANSACTION_REPEATABLE_READ:不容許髒讀和不可重複的讀,容許虛讀.
TRANSACTION_SERIALIZABLE:不容許髒讀、不可重複的讀和虛讀.
髒讀:一個事務對數據進行更新,但事務尚未提交,另外一個事務就能夠取到該事務沒有提交的更新結果。
不可重複讀:同一個事務在整個事務過程當中對同一筆數據進行屢次讀取,每次讀取結果都不一樣。
虛讀:同一個查詢在整個事務過程當中屢次執行後,查詢所得的結果集是不同的。虛讀針對的是多條記錄。
不可重複讀:列值的不一樣; 虛讀:記錄數量的不一樣。