源码-mybatis-01-SqlSessionFactory创建_weixin_30849591的博客-程序员秘密

技术标签: java  数据库  

0.总概

 

 
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类;
 
 
 

转载于:https://www.cnblogs.com/nedhome/p/10413239.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30849591/article/details/96589122

智能推荐

office16 工具栏添加 mathtype_cgrowth的博客-程序员秘密

文章目录0 简介1 word 中的操作(确认MathType没问题)2 MathPage操作2.1 MathPage.WLL 文件2.2 MathType Commands 6 For Word 2013 文件3 将复制文件粘贴到 word 目录下4 完工5 注意0 简介解决安装 mathtype 后,word 工具栏不显示 mathtype 的问题 。工具版本及系统环境:MathTyp...

layui加载流java实现_method method加载流_lzm990311的博客-程序员秘密

效果图:导入layui的css和js文件 &lt;link rel="stylesheet" href="${pageContext.request.contextPath}/layui/css/layui.css" media="all"&gt; &lt;script src="${pageContext.request.contextPath}/layui/layui.j...

连续特征离散化的方法_YJ660的博客-程序员秘密

在FFM算法编码之前突然考虑到标准化的问题,例如大多数的属性都是0-1,出现的部分连续属性比如价格可能会很大,这些的情况会不会影响FFM的结果。首先在网上搜了一下,连续特征离散化处理起到的效果是什么,这里引用一下知乎的回答作者:严林链接:https://www.zhihu.com/question/31989952/answer/54184582来源:知乎著作权归作者所有。

gateway-nacos-knife4j整合加访问权限控制(详细教程适合新手入门)_knife4j 权限_FREE_GIFT_白给怪的博客-程序员秘密

文章目录子模块配置gateway模块配置最近学习到微服务这块,子模块一个一个的swagger切换调试非常麻烦,于是想聚合在网关,研究了一段时间,发现网上的教程对新手很不友好,所以自己学习了之后整理出来供springboot项目改造成springcloud项目的小伙伴参考,适合新手入门子模块配置需要:1.新增一个config文件2.改动yaml文件3.pom文件新增依赖4.controller跟pojo上增加swagger注解(略)package com.music.netsadcloudum

JVM C1 编译优化:空检查擦除_raintungli的博客-程序员秘密

1. 什么是空检查在Java里经常会判断一个对象是否为空,如果为空的对象访问方法,字段会抛出空指针异常,而空指针异常为运行异常,如果不抓取这个异常,有的时候会导致程序异常,为了解决这个问题,我们通常会在代码里显式的去判断该对象是否为空,进行为空的逻辑处理,这种做法逻辑虽然明确,但是由于空的逻辑并不是经常碰到,这样会导致有多余的逻辑分支判断。2. 隐式空检查 implicit exception我们先来看一个代码:public static int nullCheck(String valu

使用dubbo远程调用微服务上传文件接口报错_dubbo调用上传文件接口_Jayden人生的博客-程序员秘密

使用dubbo远程调用微服务上传文件接口报错原因:服务间使用dubbo的rpc远程调用,因为dubbo并不能跨系统传递MultipartFile对象解决办法:将MultipartFile对象转化为byte数组传递例如:控制层接口@ApiOperation("图片上传")@PostMapping("/imgUpload")public ResponseResult imgUpload(ImgDto imgDto, @RequestParam("file") MultipartFile file)

随便推点

linux开发板添加qt库文件_linux下QtCreator4.9安装配置qwt和qwt移植到arm开发板_微凉qazz的博客-程序员秘密

一、QtCreator安装配置qwt1、下载最新qwt库:https://sourceforge.net/projects/qwt/files/qwt/我下载的是6.1.42、安装qwt库解压qwt-6.1.4.zip,把解压得到的qwt-6.1.4文件夹拖进Ubuntu的/opt。进入qwt-6.1.4文件根目录,依次运行以下命令:qmakemakemake install以上三条命令都是在Ub...

innodb_buffer_pool_instances and innodb_buffer_pool_size的关系_Data & safety的博客-程序员秘密

把buffer pool 分成一个用户指定的单独的区域, 每个有它自己的LRU list和相关的数据结构,降低竞争在并发内存读取和写操作。这个选项只有当innodb_buffer_pool_size 值大于1GB才生效。总的buffer pool的代销是被分成多个buffer pool.为了最好的性能, 指定innodb_buffer_pool_instances and inn...

java局部内部类和匿名内部类_局部内部类和匿名内部类的区别_东非大裂谷的博客-程序员秘密

1.局部内部类java局部内部类就是在方法中定义的类,它仅在该方法中有效。因为它不能在该方法之外使用,因此它不能使用访问控制符和static修饰。它的应用场景是:在java代理模式中,可以直接在方法中用局部内部类实现某些接口或继承某些类,返回代理对象。(局部内部类只用来返回接口或父类的对象,然后就失去了它的价值)public interface InnerInterface { ...

docker运行报错:docker: Error response from daemon: No command specified._Zerlinda1129的博客-程序员秘密

mysql镜像运行报错: docker: Error response from daemon: No command specified.如图:解决方案:是由于命令没启用的缘故,所以需要在运行命令后面追加 /bin/bash如下图:问题解决,希望能帮到大家。

linux之strace命令跟踪进程的系统调用_码莎拉蒂 .的博客-程序员秘密

1 系统调用操作系统的进程空间分为用户空间和内核空间,操作系统内核直接运行在硬件上,提供设备管理、内存管理、任务调度等功能,我们用户空间不能直接调用,所以就有了系统调用(运行在用户空间的程序向操作系统内核请求需要更高权限运行的服务),系统调用提供用户程序与操作系统之间的接口。用户空间通过API请求内核空间的服务来完成其功能——内核提供给用户空间的这些API, 就是系统调用。Linux内核目前有...

推荐文章

热门文章

相关标签