环境:Mybatis 3.5.1
简单理解SqlSession
,就是一次操作数据库的会话过程,通过它可以与数据库进行交互
使用Mybatis执行数据库操作,首先要获取SqlSession
,通过它进一步获取Mapper接口代理对象,最后通过代理对象发起数据库操作
这是使用Mybatis进行数据库操作的一个Demo,通过构建DataSource
、TransactionFactory
、Environment
、Configuration
并将它们组装在一起获得SqlSessionFactory
,此后就可以通过它获取SqlSession
public class MybatisDemo {
public static void main(String[] args) {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
// 获取SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {
BlogMapper blogMapper = session.getMapper(BlogMapper.class);
blogMapper.selectBlog(1);
}
}
/**
* 获取数据源
*/
private static DataSource getDataSource() {
Properties properties = new Properties();
properties.setProperty("driver", "com.mysql.jdbc.Driver");
properties.setProperty("url",
"jdbc:mysql://localhost:3306/study?characterEncoding=UTF8");
properties.setProperty("username", "root");
properties.setProperty("password", "123456");
PooledDataSourceFactory pooledDataSourceFactory
= new PooledDataSourceFactory();
pooledDataSourceFactory.setProperties(properties);
return pooledDataSourceFactory.getDataSource();
}
/**
* 获取Mybatis的SessionFactory
*/
private static SqlSessionFactory getSqlSessionFactory() {
DataSource dataSource = getDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment
= new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
return new SqlSessionFactoryBuilder().build(configuration);
}
}
为什么要先获取SqlSession
,Mybatis通过它做了什么?
从try-with-resource里的openSession
方法,可以定位到DefaultSqlSessionFactory#openSession
,在这里可以看到获取SqlSession
时Mybatis会创建事务工厂TransactionFactory
、执行器Executor
结合在启动Mybatis时创建的Configuration
返回一个DefaultSqlSession
public class DefaultSqlSessionFactory implements SqlSessionFactory {
public SqlSession openSession(boolean autoCommit) {
return openSessionFromDataSource(
configuration.getDefaultExecutorType(), null, autoCommit);
}
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);
// 为当前会话创建执行器Executor
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()
} finally {
}
}
}
其中Mybatis利用执行器Executor
执行数据库操作,它在获取SqlSession
时通过Configuration#newExecutor
被创建出来
Executor
的创建应用了装饰者模式
,如下所示,若开启二级缓存(默认是开启的)会使用CachingExecutor
增强其他的Executor
,同时在创建Executor
之后对其进行了一次拦截器调用
public class Configuration {
protected boolean cacheEnabled = true; // 默认启用二级缓存
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor); // 装饰器模式
}
executor = (Executor) interceptorChain.pluginAll(executor); // 应用拦截器
return executor;
}
}
至此,Mybatis获取SqlSession
的过程结束,通过它为当前的数据库操作创建一个专属的执行器Executor
和事务工厂TransactionFactory
,令当前线程的数据库操作处于一个会话状态