手写源码之路(四):Mybatis框架篇(3)会话篇
上篇文章 我们知道了SqlSessionFactoryBuilder类解析配置文件构建出SqlSessionFactory,一看类名就知道使用了工厂模式了,SqlSessionFactory负责生产SqlSession对象,SqlSession就是数据库的会话了,由会话对象负责SQL语句的执行,先看看源码:
SqlSession
/**
* @author Mr.Wang
* @Description:
* @date 2019/5/11 20:01
*/
public interface MySqlSession {
/**
* 查询带条记录
*
* @param statementKey
* @param args
* @return
* @see
*/
<T> T selectOne(String statementKey, Object[] args);
/**
* 查询多条记录
*
* @param statementKey
* @param args
* @return
* @see
*/
<E> List<E> selectList(String statementKey, Object[] args);
/**
* 查询记录返回Map
*
* @param statementKey
* @param args
* @param <K>
* @param <V>
* @return
*/
<K, V> Map<K, V> selectMap(String statementKey, Object[] args);
/**
* insert
*
* @param statementKey
* @param args
*/
int insert(String statementKey, Object[] args);
/**
* update
*
* @param statementKey
* @param args
*/
int update(String statementKey, Object[] args);
/**
* delete
*
* @param statementKey
* @param args
*/
int delete(String statementKey, Object[] args);
/**
* 提交
*/
void commit();
void commit(boolean force);
/**
* 回滚
*/
void rollback();
void rollback(boolean force);
void close();
void clearCache();
/**
* 获取mapper对象
*
* @param paramClass
* @param <T>
* @return
*/
<T> T getMapper(Class<T> paramClass);
/**
* 获取配置类
*
* @return
* @see
*/
MyConfiguration getConfiguration();
/**
* 获取数据库连接
*
* @return
*/
Connection getConnection();
}
SqlSessionFactory
/**
* @author Mr.Wang
* @Description: session工厂
* @date 2019/5/11 17:40
*/
public interface MySqlSessionFactory {
/**
* 打开session
*
* @return
*/
MySqlSession openSession();
MySqlSession openSession(boolean autoCommit);
MySqlSession openSession(Connection connection);
MySqlSession openSession(MyTransactionIsolationLevel level);
MySqlSession openSession(MyExecutorType execType);
MySqlSession openSession(MyExecutorType execType, boolean autoCommit);
MySqlSession openSession(MyExecutorType execType, MyTransactionIsolationLevel level);
MySqlSession openSession(MyExecutorType execType, Connection connection);
MyConfiguration getConfiguration();
}
SqlSession实现类:DefaultSqlSession
SqlSessionFactory实现类:DefaultSqlSessionFactory
DefaultSqlSession
/**
* @author Mr.Wang
* @Description:
* @date 2019/8/26 19:28
*/
public class MyDefaultSqlSession implements MySqlSession {
private final MyConfiguration configuration;
private final MyExecutor executor;
private final boolean autoCommit;
private boolean dirty;
public MyDefaultSqlSession(MyConfiguration configuration, MyExecutor executor) {
this(configuration, executor, false);
}
public MyDefaultSqlSession(MyConfiguration configuration, MyExecutor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}
@Override
public <T> T selectOne(String statementKey, Object[] args) {
List<T> list = this.selectList(statementKey, args);
if (list.size() == 1) {
return list.get(0);
} else if (list.size() > 1) {
throw new RuntimeException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
@Override
public <T> List<T> selectList(String statementKey, Object[] args) {
try {
MyMappedStatement mappedStatement = configuration.getMappedStatement(statementKey);
return executor.query(mappedStatement, args);
} catch (Exception e) {
throw new RuntimeException("Error querying database. Cause: " + e, e);
}
}
@Override
public <K, V> Map<K, V> selectMap(String statementKey, Object[] args) {
return null;
}
@Override
public int insert(String statementKey, Object[] args) {
return update(statementKey, args);
}
@Override
public int update(String statementKey, Object[] args) {
try {
dirty = true;
MyMappedStatement myMapperStatement = configuration.getMappedStatement(statementKey);
return executor.update(myMapperStatement, args);
} catch (Exception e) {
throw new RuntimeException("Error updating database. Cause: " + e, e);
}
}
@Override
public int delete(String statementKey, Object[] args) {
return update(statementKey, args);
}
@Override
public void commit() {
commit(false);
}
@Override
public void commit(boolean force) {
try {
executor.commit(isCommitOrRollbackRequired(force));
dirty = false;
} catch (Exception e) {
throw new RuntimeException("Error committing transaction. Cause: " + e, e);
}
}
@Override
public void rollback() {
rollback(false);
}
@Override
public void rollback(boolean force) {
try {
executor.rollback(isCommitOrRollbackRequired(force));
dirty = false;
} catch (Exception e) {
throw new RuntimeException("Error rolling back transaction. Cause: " + e, e);
}
}
@Override
public void close() {
try {
executor.close(isCommitOrRollbackRequired(false));
dirty = false;
} finally {
}
}
@Override
public void clearCache() {
executor.clearLocalCache();
}
@Override
public <T> T getMapper(Class<T> type) {
return configuration.<T>getMapper(type, this);
}
@Override
public MyConfiguration getConfiguration() {
return this.configuration;
}
@Override
public Connection getConnection() {
try {
return executor.getTransaction().getConnection();
} catch (SQLException e) {
throw new RuntimeException("Error getting a new connection. Cause: " + e, e);
}
}
private boolean isCommitOrRollbackRequired(boolean force) {
return (!autoCommit && dirty) || force;
}
}
DefaultSqlSessionFactory
/**
* @author Mr.Wang
* @Description:
* @date 2019/8/26 19:44
*/
public class MyDefaultSqlSessionFactory implements MySqlSessionFactory {
public static MySqlSession sqlSession;
private MyConfiguration configuration;
public MyDefaultSqlSessionFactory(MyConfiguration configuration) {
this.configuration = configuration;
}
@Override
public MySqlSession openSession() {
sqlSession = openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
return sqlSession;
}
@Override
public MySqlSession openSession(boolean autoCommit) {
sqlSession = openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
return sqlSession;
}
@Override
public MySqlSession openSession(Connection connection) {
sqlSession = openSessionFromConnection(configuration.getDefaultExecutorType(), connection);
return sqlSession;
}
@Override
public MySqlSession openSession(MyTransactionIsolationLevel level) {
sqlSession = openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
return sqlSession;
}
@Override
public MySqlSession openSession(MyExecutorType execType) {
sqlSession = openSessionFromDataSource(execType, null, false);
return sqlSession;
}
@Override
public MySqlSession openSession(MyExecutorType execType, boolean autoCommit) {
sqlSession = openSessionFromDataSource(execType, null, autoCommit);
return sqlSession;
}
@Override
public MySqlSession openSession(MyExecutorType execType, MyTransactionIsolationLevel level) {
sqlSession = openSessionFromDataSource(execType, level, false);
return sqlSession;
}
@Override
public MySqlSession openSession(MyExecutorType execType, Connection connection) {
sqlSession = openSessionFromConnection(execType, connection);
return sqlSession;
}
@Override
public MyConfiguration getConfiguration() {
return this.configuration;
}
private MySqlSession openSessionFromDataSource(MyExecutorType execType, MyTransactionIsolationLevel level, boolean autoCommit) {
MyTransaction tx = null;
try {
//获取环境对象
final MyEnvironment environment = configuration.getEnvironment();
//获取事务工厂对象
final MyTransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
//创建事务对象
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//创建执行器对象
final MyExecutor executor = configuration.newExecutor(tx, execType);
//创建数据库会话对象
return new MyDefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx);
throw new RuntimeException("Error opening session. Cause: " + e, e);
}
}
private MySqlSession openSessionFromConnection(MyExecutorType execType, Connection connection) {
try {
boolean autoCommit;
try {
autoCommit = connection.getAutoCommit();
} catch (SQLException e) {
autoCommit = true;
}
//获取环境对象
final MyEnvironment environment = configuration.getEnvironment();
//获取事务工厂对象
final MyTransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
//创建事务对象
final MyTransaction tx = transactionFactory.newTransaction(connection);
//创建执行器对象
final MyExecutor executor = configuration.newExecutor(tx, execType);
//创建数据库会话对象
return new MyDefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
throw new RuntimeException("Error opening session. Cause: " + e, e);
}
}
private MyTransactionFactory getTransactionFactoryFromEnvironment(MyEnvironment environment) {
if (environment == null || environment.getTransactionFactory() == null) {
return new MyManagedTransactionFactory();
}
return environment.getTransactionFactory();
}
private void closeTransaction(MyTransaction tx) {
if (tx != null) {
try {
tx.close();
} catch (SQLException ignore) {
}
}
}
}
可以看到,SqlSessionFactory负责打开数据库会话,SqlSession负责SQL语句的执行,有了SqlSession对象我们就可以调用getMapper方法去获取Mapper对象了。