主要分析了構建SqlSessionFactory的過程中配置文件的讀取.
這次重點分析mybatis的事務管理器
仍舊從官網給的例子着手分析,配置文件mybatis-config.xml
<?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兩個結點.
environments:環境,mybatis可以配置多個環境即可以將 SQL 映射應用於多種數據庫之中.如開發,測試,生產對應不同的數據庫.
mappers:映射器,提供映射文件的地址.
在environment下的transactionManager就是現在要重點分析的對象.
mybatis中有兩種類型的事務管理器,JDBC和MANAGED.
JDBC:直接使用了 JDBC 的提交和回滾設置,它依賴於從數據源得到的連接來管理事務範圍。
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:不允許髒讀、不可重複的讀和虛讀.
髒讀:一個事務對數據進行更新,但事務還沒有提交,另一個事務就可以取到該事務沒有提交的更新結果。
不可重複讀:同一個事務在整個事務過程中對同一筆數據進行多次讀取,每次讀取結果都不同。
虛讀:同一個查詢在整個事務過程中多次執行後,查詢所得的結果集是不一樣的。虛讀針對的是多條記錄。
不可重複讀:列值的不同; 虛讀:記錄數量的不同。