SqlSessionFactory
从SqlSessionFactory
说起吧,org.apache.ibatis.session.SqlSessionFactory
接口。通过openSession()
可以打开连接操作sql
,里面的方法有如下:
Sql执行的过程
-
例如下面的测试代码,运行一个用注解方式执行的
Sql
,用xml
方式配置执行测试代码可见博客:https://blog.csdn.net/qq_37248504/article/details/109861871 -
测试部分被代码,完整代码见提交记录https://gitee.com/Marlon_Brando/back/commit/83b5e69e30ea9238fe824a395ce951767d8a33bd
@Component
public class MybatisConfig {
private static final Logger logger = LoggerFactory.getLogger(MybatisConfig.class);
@Autowired
private DataSource dataSource;
@Bean
public SqlSessionFactory sqlSessionFactory() {
SqlSession sqlSession = null;
try {
// 采用Mybatis的JDBC事务方式
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("myenverniement", transactionFactory, dataSource);
// 创建Configuration对象
Configuration configuration = new Configuration(environment);
configuration.addMapper(TestMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
sqlSession = sqlSessionFactory.openSession();
TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
Map<String, Object> result = testMapper.testOne();
logger.info("result:{}", result);
logger.info(LogConstant.LOG_SUCCESS_PREFIX + "SqlSessionFactory配置完成");
return sqlSessionFactory;
} catch (Exception e) {
logger.error(LogConstant.ERROR, e.getMessage());
return null;
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
}
定义事务提交方式
// 采用Mybatis的JDBC事务方式
TransactionFactory transactionFactory = new JdbcTransactionFactory();
初始化Mybatis Environment
Environment.java
源码如下:构造方法参数(事务、数据源)
public final class Environment {
private final String id;
// 事务
private final TransactionFactory transactionFactory;
// 数据源
private final DataSource dataSource;
public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) {
if (id == null) {
throw new IllegalArgumentException("Parameter 'id' must not be null");
} else if (transactionFactory == null) {
throw new IllegalArgumentException("Parameter 'transactionFactory' must not be null");
} else {
this.id = id;
if (dataSource == null) {
throw new IllegalArgumentException("Parameter 'dataSource' must not be null");
} else {
this.transactionFactory = transactionFactory;
this.dataSource = dataSource;
}
}
}
}
初始化Configuration
MyBatis所有的配置信息都保存在Configuration对象之中,配置文件中的大部分配置都会存储到该类中。构造方法参数是Environment
,上面已经说过Environment
了。
public Configuration(Environment environment) {
this();
this.environment = environment;
}
- 可以添加
Mapper
添加数据接收对象等等。 Mybatis
和SpringBoot
集成之后,在启动服务的时候,会扫描xml文件、mapper中的接口,将所有的配置信息配置到Configuration
中,之后用dao层操作的时候,拿出相应的sql
进行执行。
初始化SqlSessionFactory
// 得到SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
build()
参数有如下种类,其实都是一样的道理,
得到操作Sql的接口
sqlSession = sqlSessionFactory.openSession();
TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
Map<String, Object> result = testMapper.testOne();
openSession()
源码:
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
DefaultSqlSession var8;
try {
Environment environment = this.configuration.getEnvironment();
// 获取事务提交方式
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 获取执行器
Executor executor = this.configuration.newExecutor(tx, execType);
// 返回调用dao 的session对象
var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
} catch (Exception var12) {
this.closeTransaction(tx);
throw ExceptionFactory.wrapException("Error opening session. Cause: " + var12, var12);
} finally {
ErrorContext.instance().reset();
}
return var8;
}
getMapper执行
TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
Map<String, Object> result = testMapper.testOne();
- 源码:
// 从configuration中获得对应的接口
public <T> T getMapper(Class<T> type) {
return this.configuration.getMapper(type, this);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return this.mapperRegistry.getMapper(type, sqlSession);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// mapper 代理
MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
} else {
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception var5) {
throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
}
}
}
- 根据type类型,从
MapperRegistry
对象中的knownMappers
获取到当前类型对应的代理工厂类,然后通过代理工厂类生成对应Mapper的代理类。 - 最终获取到我们接口对应的代理类
TestMapper
对象
- 实现
InvocationHandler
,使用JDK代理
mapperRegistry 中的属性加载时间
- 在初始化SqlSessionFactory对象的时候,解析
xml
文件,
- 解析的过程中会解析
mapper
中用注解标记的方法,解析xml
映射文件,还会对Mapper
接口中的方法进行解析,并将每个方法的全限定类名作为key
存入存入Configuration
中的mappedStatements
属性。