SqlSessionFactoryBuilder
- SqlSessionFactory
- SqlSession
- Configuration
在spring 中配置mybatis 需要配置SqlSessionFactory实例。例如:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="dataSource" ref="dataWriteSource"/>
</bean>
1.由SqlSessionFactoryBean构建sqlSessionFactory,构建过程如下:
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
private Resource configLocation;
private Resource[] mapperLocations;
private DataSource dataSource;
private TransactionFactory transactionFactory;
private Properties configurationProperties;
private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
private SqlSessionFactory sqlSessionFactory;
private String environment = SqlSessionFactoryBean.class.getSimpleName();
private boolean failFast;
private Interceptor[] plugins;
private TypeHandler<?>[] typeHandlers;
private String typeHandlersPackage;
private Class<?>[] typeAliases;
private String typeAliasesPackage;
private Class<?> typeAliasesSuperType;
private DatabaseIdProvider databaseIdProvider;
private ObjectFactory objectFactory;
private ObjectWrapperFactory objectWrapperFactory;
...
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.dataSource, "Property 'dataSource' is required");
Assert.notNull(this.sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
this.sqlSessionFactory = this.buildSqlSessionFactory();
}
protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
...
}
...
}
1.1重点分析buildSqlSessionFactory过程1.1.1.首先构建Configuration组件
XMLConfigBuilder xmlConfigBuilder = null;
Configuration configuration;
if(this.configLocation != null) {
xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), (String)null, this.configurationProperties);
configuration = xmlConfigBuilder.getConfiguration();
} else {
if(logger.isDebugEnabled()) {
logger.debug("Property 'configLocation' not specified, using default MyBatis Configuration");
}
configuration = new Configuration();
configuration.setVariables(this.configurationProperties);
}
...
if(xmlConfigBuilder != null) {
try {
xmlConfigBuilder.parse();
if(logger.isDebugEnabled()) {
logger.debug("Parsed configuration file: '" + this.configLocation + "'");
}
} catch (Exception var23) {
throw new NestedIOException("Failed to parse config resource: " + this.configLocation, var23);
} finally {
ErrorContext.instance().reset();
}
}
xmlConfigBuilder解析mybatis-config.xml内容构建Configuration
public Configuration parse() {
if(this.parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
} else {
this.parsed = true;
this.parseConfiguration(this.parser.evalNode("/configuration"));
return this.configuration;
}
}
private void parseConfiguration(XNode root) {
try {
this.propertiesElement(root.evalNode("properties"));
this.typeAliasesElement(root.evalNode("typeAliases"));
this.pluginElement(root.evalNode("plugins"));
this.objectFactoryElement(root.evalNode("objectFactory"));
this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
this.settingsElement(root.evalNode("settings"));
this.environmentsElement(root.evalNode("environments"));
this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
this.typeHandlerElement(root.evalNode("typeHandlers"));
this.mapperElement(root.evalNode("mappers"));
} catch (Exception var3) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
}
}
1.1.2由SqlSessionFactoryBuilder构建SqlSessionFactory组件
return this.sqlSessionFactoryBuilder.build(configuration);
public class SqlSessionFactoryBuilder {
...
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
}
2.1SqlSession由sqlSessionFactory构建
package org.apache.ibatis.session;
import java.sql.Connection;
public interface SqlSessionFactory {
SqlSession openSession();
SqlSession openSession(boolean var1);
SqlSession openSession(Connection var1);
SqlSession openSession(TransactionIsolationLevel var1);
SqlSession openSession(ExecutorType var1);
SqlSession openSession(ExecutorType var1, boolean var2);
SqlSession openSession(ExecutorType var1, TransactionIsolationLevel var2);
SqlSession openSession(ExecutorType var1, Connection var2);
Configuration getConfiguration();
}
SqlSession由通过DataSource或者Connection打开
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);
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;
}
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
DefaultSqlSession var8;
try {
boolean autoCommit;
try {
autoCommit = connection.getAutoCommit();
} catch (SQLException var13) {
autoCommit = true;
}
Environment environment = this.configuration.getEnvironment();
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
Transaction tx = transactionFactory.newTransaction(connection);
Executor executor = this.configuration.newExecutor(tx, execType);
var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
} catch (Exception var14) {
throw ExceptionFactory.wrapException("Error opening session. Cause: " + var14, var14);
} finally {
ErrorContext.instance().reset();
}
return var8;
}
总结:
组件生命周期:
理解各个组件的生命周期,能够帮助我们更好的使用Mybatis
SqlSessionFactoryBuilder:这个是帮助我们构建SqlSessionFactory的,一旦构建完成就会回收它,所以此生命周期应该是方法级别的
SqlSessionFactory: 这个是创建SqlSession的,而SqlSession是会话级别的,如果我们每次创建SqlSession都需要重新走上面的流程构建SqlSessionFactroy的话,不仅费时间,而且性能也是极差的。所以它的生命周期应该是应用的生命周期,项目初始化的时候通过单例模式构建它。
Configuration: 作为Mybatis配置集合,生命周期也应该是应用的整个生命周期
SqlSession: SqlSession是一个会话,可以把它当作JDBC的Connectiond对象,当需要操作一次数据库的时候我们就构建一次。操作完需要关闭它,所以它的生命周期应该是方法级别
SqlSessionFactoryBuilder
- SqlSessionFactory
- SqlSession
- Configuration
在spring 中配置mybatis 需要配置SqlSessionFactory实例。例如:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="dataSource" ref="dataWriteSource"/>
</bean>
1.由SqlSessionFactoryBean构建sqlSessionFactory,构建过程如下:
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
private Resource configLocation;
private Resource[] mapperLocations;
private DataSource dataSource;
private TransactionFactory transactionFactory;
private Properties configurationProperties;
private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
private SqlSessionFactory sqlSessionFactory;
private String environment = SqlSessionFactoryBean.class.getSimpleName();
private boolean failFast;
private Interceptor[] plugins;
private TypeHandler<?>[] typeHandlers;
private String typeHandlersPackage;
private Class<?>[] typeAliases;
private String typeAliasesPackage;
private Class<?> typeAliasesSuperType;
private DatabaseIdProvider databaseIdProvider;
private ObjectFactory objectFactory;
private ObjectWrapperFactory objectWrapperFactory;
...
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.dataSource, "Property 'dataSource' is required");
Assert.notNull(this.sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
this.sqlSessionFactory = this.buildSqlSessionFactory();
}
protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
...
}
...
}
1.1重点分析buildSqlSessionFactory过程1.1.1.首先构建Configuration组件
XMLConfigBuilder xmlConfigBuilder = null;
Configuration configuration;
if(this.configLocation != null) {
xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), (String)null, this.configurationProperties);
configuration = xmlConfigBuilder.getConfiguration();
} else {
if(logger.isDebugEnabled()) {
logger.debug("Property 'configLocation' not specified, using default MyBatis Configuration");
}
configuration = new Configuration();
configuration.setVariables(this.configurationProperties);
}
...
if(xmlConfigBuilder != null) {
try {
xmlConfigBuilder.parse();
if(logger.isDebugEnabled()) {
logger.debug("Parsed configuration file: '" + this.configLocation + "'");
}
} catch (Exception var23) {
throw new NestedIOException("Failed to parse config resource: " + this.configLocation, var23);
} finally {
ErrorContext.instance().reset();
}
}
xmlConfigBuilder解析mybatis-config.xml内容构建Configuration
public Configuration parse() {
if(this.parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
} else {
this.parsed = true;
this.parseConfiguration(this.parser.evalNode("/configuration"));
return this.configuration;
}
}
private void parseConfiguration(XNode root) {
try {
this.propertiesElement(root.evalNode("properties"));
this.typeAliasesElement(root.evalNode("typeAliases"));
this.pluginElement(root.evalNode("plugins"));
this.objectFactoryElement(root.evalNode("objectFactory"));
this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
this.settingsElement(root.evalNode("settings"));
this.environmentsElement(root.evalNode("environments"));
this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
this.typeHandlerElement(root.evalNode("typeHandlers"));
this.mapperElement(root.evalNode("mappers"));
} catch (Exception var3) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
}
}
1.1.2由SqlSessionFactoryBuilder构建SqlSessionFactory组件
return this.sqlSessionFactoryBuilder.build(configuration);
public class SqlSessionFactoryBuilder {
...
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
}
2.1SqlSession由sqlSessionFactory构建
package org.apache.ibatis.session;
import java.sql.Connection;
public interface SqlSessionFactory {
SqlSession openSession();
SqlSession openSession(boolean var1);
SqlSession openSession(Connection var1);
SqlSession openSession(TransactionIsolationLevel var1);
SqlSession openSession(ExecutorType var1);
SqlSession openSession(ExecutorType var1, boolean var2);
SqlSession openSession(ExecutorType var1, TransactionIsolationLevel var2);
SqlSession openSession(ExecutorType var1, Connection var2);
Configuration getConfiguration();
}
SqlSession由通过DataSource或者Connection打开
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);
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;
}
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
DefaultSqlSession var8;
try {
boolean autoCommit;
try {
autoCommit = connection.getAutoCommit();
} catch (SQLException var13) {
autoCommit = true;
}
Environment environment = this.configuration.getEnvironment();
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
Transaction tx = transactionFactory.newTransaction(connection);
Executor executor = this.configuration.newExecutor(tx, execType);
var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
} catch (Exception var14) {
throw ExceptionFactory.wrapException("Error opening session. Cause: " + var14, var14);
} finally {
ErrorContext.instance().reset();
}
return var8;
}
总结:
组件生命周期:
理解各个组件的生命周期,能够帮助我们更好的使用Mybatis
SqlSessionFactoryBuilder:这个是帮助我们构建SqlSessionFactory的,一旦构建完成就会回收它,所以此生命周期应该是方法级别的
SqlSessionFactory: 这个是创建SqlSession的,而SqlSession是会话级别的,如果我们每次创建SqlSession都需要重新走上面的流程构建SqlSessionFactroy的话,不仅费时间,而且性能也是极差的。所以它的生命周期应该是应用的生命周期,项目初始化的时候通过单例模式构建它。
Configuration: 作为Mybatis配置集合,生命周期也应该是应用的整个生命周期
SqlSession: SqlSession是一个会话,可以把它当作JDBC的Connectiond对象,当需要操作一次数据库的时候我们就构建一次。操作完需要关闭它,所以它的生命周期应该是方法级别