1.SqlSessionFactory在mybatis只要创建一次;
import com.suntek.vdm.gw.util.AESEncipher;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.*;
import java.util.Properties;
/**
* @author Binglong
*/
public class MybatisUtils {
private static SqlSessionFactory factory=null;
/**
* 获取SqlSessionFactory,只创建一次
* @return SqlSessionFactory
*/
private static SqlSessionFactory getSqlSessionFactory() {
if (null != factory){
return factory;
}
synchronized (SqlSessionFactory.class){
factory = getFactory();
}
return factory;
}
private static SqlSessionFactory getFactory() {
try {
//读取配置文件
Reader reader= Resources.getResourceAsReader("mybatis.xml");
//创建SQLSessionFactory
return new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
classpath路径下的mybatis.xml配置文件(以后详解配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--引入配置-->
<properties resource="conf/db.properties"/>
<!--sql打印 -->
<!--<settings>-->
<!--<setting name="logImpl" value="STDOUT_LOGGING"/>-->
<!--</settings>-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="net.sourceforge.jtds.jdbc.Driver"/>
<!--<property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>-->
<property name="url" value="${url}"/>
<!--<property name="username" value="${username}"/>-->
<!--<property name="password" value="${password}"/>-->
<!--poolMaximumIdleConnections是空闲连接数,就是没有处理请求的连接,默认是5-->
<property name="poolMaximumIdleConnections" value="5"/>
<!--poolMaximumActiveConnections是最大的活动连接数,活动连接,就是正在与数据库交互的连接,默认是10-->
<property name="poolMaximumActiveConnections" value="50"/>
<!--<property name="poolPingQuery" value="SELECT 1 FROM VDM_VR_NODE" />-->
<!--<property name="poolPingEnabled" value="true" />-->
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/ned/gw/mapping/UserMapper.xml"></mapper>
</mappers>
</configuration>
2.SqlSessionFactoryBuilder构建
从上面可以看到,SqlSessionFactory主要是由SqlSessionFactoryBuilder创建,而SqlSessionFactoryBuilder提供了两种方法创建,一种基于Reader,另一种基于InputStream;两种方式都是把配置封装成XMLConfigBuilder,然后通过 new DefaultSqlSessionFactory(config)创建;
有构造方法可以看,也要传入Properties 配置;
package org.apache.ibatis.session;
import java.io.*;
import java.util.Properties;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
public class SqlSessionFactoryBuilder {
public SqlSessionFactoryBuilder() {
}
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
SqlSessionFactory var5;
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
var5 = this.build(parser.parse());
} catch (Exception var14) {
throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException var13) {
}
}
return var5;
}
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
SqlSessionFactory var5;
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
var5 = this.build(parser.parse());
} catch (Exception var14) {
throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException var13) {
}
}
return var5;
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
}
3.XMLConfigBuilder解析
a.而XMLConfigBuilder最终把Reader和InputStream都封装成一个XPathParser(从字面上看估计是一个路径解析器);
b.获取到XMLConfigBuilder,还调用了其parse()方法,也就是解析配置文件(解析详情以后分析);
c.最终把所有配置封装在Configuration中,而这个Configuration正是SqlSessioFactory实现类DefaultSqlSessioFactory的重要属性;
值得关注的是这里XMLConfigBuilder创建时Properties props参数
public class XMLConfigBuilder extends BaseBuilder {
private boolean parsed;
private XPathParser parser;
private String environment;
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;
}
//解析
public Configuration parse() {
if (this.parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
} else {
this.parsed = true;
//从配置文件configuration节点作为根节点开始
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);
}
}
}
public class XPathParser {
private Document document ;
private boolean validation; //是否开启验证
private EntityResolver entityResolver ; //用于加载本地D T D 文件
private Properties variables ; // mybatis.xml 中<propteries> 标签定义的键位对集合
private XPath xpath ; // XPath 对象
}
public class DefaultSqlSessionFactory implements SqlSessionFactory {
private final Configuration configuration;
…………
}
4.总结
SqlSessionFactory创建过程是把配置文件通过InputStream或Reader两种方式传到SqlSessionFactoryBuilder,然后SqlSessionFactoryBuilder创建一个XMLConfigBuilder,把配置信息放到XMLConfigBuilder中然后调用parse方法进行一系列解析,最终生成一个Configuration,而这个Configuration正式DefaultSqlSessionFactory的唯一属性,也就是把Configuration传入new一个DefaultSqlSessionFactory;
遗留问题
mybaitis.xml解析解析细节;
Configuration类;