赞
踩
SqlSession对象 表示 MyBaits框架 与 数据库 建立的会话
可以通过SqlSession实例 完成 对数据库的增删改查操作
为了简化流程描述,将SqlSession的创建过程拆解为3个阶段
MyBatis的主配置文件和Mapper配置都使用的是XML格式
MyBatis中的Configuration组件 用于 描述 主配置文件信息,框架 在启动时 会解析 XML配置,将 配置信息 转换为 Configuration对象
JDK API中提供了3种方式解析XML,分别为DOM、SAX和XPath
在这3种方式中,API最易于使用的就是XPath方式,MyBatis框架中也采用XPath方式解析XML文件中的配置信息
为了简化XPath解析操作,MyBatis通过XPathParser工具类 封装了 对XML的解析操作
同时使用XNode类增强了 对XML节点的操作
使用XNode对象,可以很方便地获取节点的属性、子节点等信息
Configuration是MyBatis中比较重要的组件,主要有以下3个作用:
在SqlSession实例化前,首先解析 MyBatis主配置文件 及 所有Mapper文件,创建Configuration实例
MyBatis通过XMLConfigBuilder类 完成Configuration实例的构建工作
XMLConfigBuilder继承了BaseBuilder,BaseBuilder中有Configuration成员变量
XMLConfigBuilder有许多构造方法,主要是两类,一类是字节流读取,一类是字符读取
public XMLConfigBuilder(Reader reader, String environment, Properties props) { this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props); } public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) { this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props); } // 最后走的都是这个方法 private XMLConfigBuilder(XPathParser parser, String environment, Properties props) { super(new Configuration()); ErrorContext.instance().resource("SQL Mapper Configuration"); this.configuration.setVariables(props); this.parsed = false; this.environment = environment; this.parser = parser; }
接下来通过parse
方法返回Configuration实例
public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; parseConfiguration(parser.evalNode("/configuration")); return configuration; } private void parseConfiguration(XNode root) { try { // issue #117 read properties first propertiesElement(root.evalNode("properties")); Properties settings = settingsAsProperties(root.evalNode("settings")); loadCustomVfs(settings); loadCustomLogImpl(settings); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); reflectorFactoryElement(root.evalNode("reflectorFactory")); // 这里把解析后的root节点各种信息都set in Configuration属性 settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); // set mapper信息inConfiguration属性中 mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
MyBatis主配置文件中所有标签的用途如下
MyBatis框架启动后,首先创建Configuration实例,然后解析所有配置信息,将解析后的配置信息存放在Configuration实例中
注意:Configuration类中有mapperRegistry成员变量,mapperRegistry 会在后面执行Mapper过程中用到
protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
XMLConfigBuilder#parse方法是被SqlSessionFactoryBuilder类在SqlSessionFactoryBuilder#build中调用的
SqlSessionFactoryBuilder#build返回一个SqlSessionFactory实例
然后SqlSessionFactory实例的openSession()方法创建一个SqlSession实例
MyBatis中的SqlSession实例使用工厂模式创建
在创建SqlSession实例 之前 需要 先创建 SqlSessionFactory工厂实例
然后调用SqlSessionFactory实例的openSession()方法,例如下面代码:
Reader reader = Resources.getResourceAsReader("xx/xx/xx/mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props);
Configuration configuration = factory.getConfiguration();
为了创建SqlSessionFactory实例,首先创建了一个SqlSessionFactoryBuilder实例
以MyBatis主配置文件输入流作为参数,调用SqlSessionFactoryBuilder实例的build()方法
build
方法也主要有两类,一类是字符流,一类是字节
build方法中先构造XMLConfigBuilder实例
然后通过XMLConfigBuilder#parse方法得到一个Configuration实例
再使用build方法通过Configuration实例 得到一个 SqlSessionFactory实例
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
SqlSessionFactory接口只有一个默认的实现,即DefaultSqlSessionFactory
在上面的代码中,重载的build()方法中以Configuration实例作为参数,通过new关键字创建了一个DefaultSqlSessionFactory实例
DefaultSqlSessionFactory类中有各种openSession方法,可以得到一个SqlSession实例
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { // 获取Mybatis主配置文件 配置的 环境信息 final Environment environment = configuration.getEnvironment(); // 创建 事务管理器工厂 final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); // 创建 事务管理器 tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); // 根据 Mybatis主配置文件中 制定的ExecutorType 创建对应的 Executor 实例 final Executor executor = configuration.newExecutor(tx, execType); // 创建 DefaultSqlSession实例 return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) { try { boolean autoCommit; try { autoCommit = connection.getAutoCommit(); } catch (SQLException e) { // Failover to true, as most poor drivers // or databases won't support transactions autoCommit = true; } final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); final Transaction tx = transactionFactory.newTransaction(connection); final Executor executor = configuration.newExecutor(tx, execType); return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
MyBatis提供了两种事务管理器,分别为JdbcTransaction和ManagedTransaction
JdbcTransaction 是使用 JDBC中的Connection对象 实现 事务管理的
ManagedTransaction表示 事务 由外部容器 管理
这两种事务管理器分别由对应的工厂类JdbcTransactionFactory和ManagedTransactionFactory创建
事务管理器对象创建完毕后,接着调用Configuration对象的newExecutor()方法,根据MyBatis主配置文件中指定的Executor类型创建对应的Executor对象
最后以Executor对象和Configuration对象作为参数,通过Java中的new关键字创建一个DefaultSqlSession对象
DefaultSqlSession对象中持有Executor对象的引用,真正执行SQL操作的是Executor对象
@Override
public <T> T getMapper(Class<T> type) {
return configuration.getMapper(type, this);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
getMapper的创建及执行过程就是接下来要整理的内容
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。