Mybatis3.5.1源码分析
- Mybatis-SqlSessionFactoryBuilder,XMLConfigBuilder,XPathParser源码解析
- Mybatis-Configuration源码解析
- Mybatis-事务对象源码解析
- Mybatis-数据源源码解析
- Mybatis缓存策略源码解析
- Mybatis-DatabaseIdProvider源码解析
- Mybatis-TypeHandler源码解析
- Mybatis-Reflector源码解析
- Mybatis-ObjectFactory,ObjectWrapperFactory源码分析
- Mybatis-Mapper各类标签封装类源码解析
- Mybatis-XMLMapperBuilder,XMLStatmentBuilder源码分析
- Mybatis-MapperAnnotationBuilder源码分析
- [Mybatis-MetaObject,MetaClass源码解析]https://www.jianshu.com/p/f51fa552f30a)
- Mybatis-LanguageDriver源码解析
- Mybatis-SqlSource源码解析
- Mybatis-SqlNode源码解析
- Mybatis-KeyGenerator源码解析
- Mybatis-Executor源码解析
- Mybatis-ParameterHandler源码解析
- Mybatis-StatementHandler源码解析
- Mybatis-DefaultResultSetHandler(一)源码解析
- Mybatis-DefaultResultSetHandler(二)源码解析
- Mybatis-ResultHandler,Cursor,RowBounds 源码分析
- Mybatis-MapperProxy源码解析
- Mybatis-SqlSession源码解析
- Mybatis-Interceptor源码解析
TransactionIsolationLevel
/**
* Copyright 2009-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.session;
import java.sql.Connection;
/**
* 事务隔离等级
*
* 参考博客:https://blog.csdn.net/jiangwei0910410003/article/details/24960785
*
* @author Clinton Begin
*/
public enum TransactionIsolationLevel {
NONE(Connection.TRANSACTION_NONE),
/**
*(读取未提交内容)级别
*/
READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED),
/**
* 读取提交内容
*/
READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),
/**
* 可重读
*/
REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),
/**
* 串行化
*/
SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE);
private final int level;
TransactionIsolationLevel(int level) {
this.level = level;
}
public int getLevel() {
return level;
}
}
TransactionFactory
/**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.transaction;
import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.ibatis.session.TransactionIsolationLevel;
/**
* Creates {@link Transaction} instances.
* 事务工厂
* @author Clinton Begin
*/
public interface TransactionFactory {
/**
* 设置属性
* Sets transaction factory custom properties.
* @param props 属性集
*/
void setProperties(Properties props);
/**
* 新建一个事务
* Creates a {@link Transaction} out of an existing connection.
* @param conn Existing database connection
* @return Transaction 事务对象
* @since 3.1.0
*/
Transaction newTransaction(Connection conn);
/**
* 新建一个事务
* Creates a {@link Transaction} out of a datasource.
* @param dataSource DataSource to take the connection from 数据源
* @param level Desired isolation level 事务隔离等级
* @param autoCommit Desired autocommit 是否自动提交
* @return Transaction 事务对象
* @since 3.1.0
*/
Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}
JdbcTransactionFactory
/**
* Copyright 2009-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.transaction.jdbc;
import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;
/**
* Creates {@link JdbcTransaction} instances.
* JDBC事务工厂
* @author Clinton Begin
*
* @see JdbcTransaction
*/
public class JdbcTransactionFactory implements TransactionFactory {
/**
* 设置属性
* @param props 属性集
*/
@Override
public void setProperties(Properties props) {
}
/**
* 新建Jdbc事务对象
* @param conn Existing database connection 数据库连接
* @return Jdbc事务对象
*/
@Override
public Transaction newTransaction(Connection conn) {
//新建Jdbc事务对象
return new JdbcTransaction(conn);
}
/**
* 新建Jdbc事务对象
* @param ds 数据源
* @param level Desired isolation level 事务隔离等级
* @param autoCommit Desired autocommit 是否自动提交
* @return Jdbc事务对象
*/
@Override
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
//新建Jdbc事务对象
return new JdbcTransaction(ds, level, autoCommit);
}
}
ManagedTransactionFactory
/**
* Copyright 2009-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.transaction.managed;
import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;
/**
* Creates {@link ManagedTransaction} instances.
* {@link ManagedTransaction} 工厂。
* @author Clinton Begin
*
* @see ManagedTransaction
*/
public class ManagedTransactionFactory implements TransactionFactory {
private boolean closeConnection = true;
/**
* 接收一个关闭连接closeConnection的属性。ManagedTransaction它默认会关闭连接,然而一些容器并不希望这样,
* 因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。
* @param props
*/
@Override
public void setProperties(Properties props) {
if (props != null) {
String closeConnectionProperty = props.getProperty("closeConnection");
if (closeConnectionProperty != null) {
closeConnection = Boolean.valueOf(closeConnectionProperty);
}
}
}
@Override
public Transaction newTransaction(Connection conn) {
return new ManagedTransaction(conn, closeConnection);
}
@Override
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
// Silently ignores autocommit and isolation level, as managed transactions are entirely
// controlled by an external manager. It's silently ignored so that
// code remains portable between managed and unmanaged configurations.
//默默地忽略autocommit和隔离级别,管理事务完全由外部控制经理。它默默地忽略代码之间仍然是便携式托管和非托管的配置。
// ManagedTransaction:MyBatis自身不会去实现事务管理,而是让程序的容器如(JBOSS,Weblogic)来实现对事务的管理
return new ManagedTransaction(ds, level, closeConnection);
}
}
Transaction
/**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.transaction;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Wraps a database connection.
* Handles the connection lifecycle that comprises: its creation, preparation, commit/rollback and close.
* 包装一个数据库连接。
* 处理连接的生命周期包括:创建、准备、提交/回滚并关闭。;
* @author Clinton Begin
*/
public interface Transaction {
/**
* 获取数据库连接
* Retrieve inner database connection.
* @return DataBase connection
* @throws SQLException
*/
Connection getConnection() throws SQLException;
/**
* 提交数据库连接
* Commit inner database connection.
* @throws SQLException
*/
void commit() throws SQLException;
/**
* 回退数据库连接
* Rollback inner database connection.
* @throws SQLException
*/
void rollback() throws SQLException;
/**
* 关闭数据库连接
* Close inner database connection.
* @throws SQLException
*/
void close() throws SQLException;
/**
* 获取事务超时时长
* Get transaction timeout if set.
* @throws SQLException
*/
Integer getTimeout() throws SQLException;
}
JdbcTransaction
/**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.transaction.jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionException;
/**
* {@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.
* JDBC事务封装
* @author Clinton Begin
*
* @see JdbcTransactionFactory
*/
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;
/**
*
* @param ds 数据库数据源
* @param desiredLevel 事务隔离级别,设置null时,隔离级别由数据库自行配置
* @param desiredAutoCommit 是否自动提交事务
*/
public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
dataSource = ds;
level = desiredLevel;
autoCommit = desiredAutoCommit;
}
/**
*
* @param connection 数据库连接
*/
public JdbcTransaction(Connection connection) {
this.connection = connection;
}
@Override
public Connection getConnection() throws SQLException {
if (connection == null) {
openConnection();
}
return connection;
}
/**
* 提交事务,在没有设置自动提交事务,才会提交事务。
* @throws SQLException
*/
@Override
public void commit() throws SQLException {
if (connection != null && !connection.getAutoCommit()) {
if (log.isDebugEnabled()) {
log.debug("Committing JDBC Connection [" + connection + "]");
}
connection.commit();
}
}
/**
* 回退事务,在没有设置自动提交事务,才会回退事务。
* @throws SQLException
*/
@Override
public void rollback() throws SQLException {
if (connection != null && !connection.getAutoCommit()) {
if (log.isDebugEnabled()) {
log.debug("Rolling back JDBC Connection [" + connection + "]");
}
connection.rollback();
}
}
/**
* 关闭连接,关闭连接之前,会设置自动提交为true,以解决有些数据库读取事务时就开始事务了和授权了提交、回滚在关闭这个连接之前的问题
* @throws SQLException
*/
@Override
public void close() throws SQLException {
if (connection != null) {
resetAutoCommit();
if (log.isDebugEnabled()) {
log.debug("Closing JDBC Connection [" + connection + "]");
}
connection.close();
}
}
/**
* 设置自动提交,
* @param desiredAutoCommit 是否自动提交
*/
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) {
// Only a very poorly implemented driver would fail here,
// and there's not much we can do about that.
throw new TransactionException("Error configuring AutoCommit. "
+ "Your driver may not support getAutoCommit() or setAutoCommit(). "
+ "Requested setting: " + desiredAutoCommit + ". Cause: " + e, e);
}
}
/**
*
* 这里相对自动提交做个解说,如果设置自动提交为真,那么数据库将会将每一个SQL语句当做一个事务来执行,为了将多条SQL当做一个事务进行提交,
* 必须将自动提交设置为false,然后进行手动提交。一般在我们的项目中,都需要将自动提交设置为false,即将自动提交关闭,使用手动提交
*
* 这个方法中通过对connection实例中的自动提交设置(真或假)进行判断,如果为false,表明不执行自动提交,则复位,重新将其设置为true。
* (自动提交的默认值为true)这个操作执行在connection关闭之前。可以看做是连接关闭之前的复位操作。
*
*/
protected void resetAutoCommit() {
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.
// mybatis 不会调用 提交/回滚 如果只是进行查找的连接
// 有些数据库读取事务时就开始事务了和授权了提交、回滚在关闭这个连接之前
// 一个解决方案是在关闭连接之前设置自动提交
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);
}
}
}
/**
* 打开数据库连接,设置事务隔离等级,设置是否自动提交
* @throws SQLException
*/
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);
}
/**
* 获取超时时长,该类并没有重写这个方法,直接返回null
* @return
* @throws SQLException
*/
@Override
public Integer getTimeout() throws SQLException {
return null;
}
}
ManagedTransaction
/**
* Copyright 2009-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.transaction.managed;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
/**
* {@link Transaction} that lets the container manage the full lifecycle of the transaction.
* Delays connection retrieval until getConnection() is called.
* Ignores all commit or rollback requests.
* By default, it closes the connection but can be configured not to do it.
* 译:
* 该类让容器管理事务的完整生命周期。
* 延迟连接恢复,直到得到连接(),忽略所有提交或者退回请求。
* 默认情况下,它将关闭连接但不可以配置。;
*
*
* ManagedTransaction:MyBatis自身不会去实现事务管理,而是让程序的容器如(JBOSS,Weblogic)来实现对事务的管理
*
*
* @author Clinton Begin
*
* @see ManagedTransactionFactory
*/
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 {
// Does nothing
}
/**
* 是个空方法
*/
@Override
public void rollback() throws SQLException {
// Does nothing
}
/**
* 关闭数据库连接,根据是否允许关闭连接closeConnection
* @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();
}
}
/**
* 打开数据库连接,设置数据库隔离级别
* @throws SQLException
*/
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;
}
}