MyBatis解析全局配置文件

MyBatis解析全局配置文件

MyBaits基础应用:

文档:MyBatis

链接:http://note.youdao.com/noteshare?id=5d41fd41d970f1af9185ea2ec0647b64

传统JDBC和Mybatis相比的弊病

传统JDBC

Connection conn = null;
PreparedStatement pstmt = null;
try {         
    // 1.加载驱动         
    Class.forName("com.mysql.jdbc.Driver");          
    // 2.创建连接         
    conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis_example", "root", "123456");           
    // SQL语句         
    String sql = "select id,user_name,create_time from t_user where id=?";          
    // 获得sql执行者         
    pstmt = conn.prepareStatement(sql);
    pstmt.setInt(1, 1);          
    // 执行查询         
    //ResultSet rs= pstmt.executeQuery();         
    pstmt.execute();
    ResultSet rs = pstmt.getResultSet();
    rs.next();
    User user = new User();
    user.setId(rs.getLong("id"));
    user.setUserName(rs.getString("user_name"));
    user.setCreateTime(rs.getDate("create_time"));
    System.out.println(user.toString());
}

传统JDBC的问题如下:

1.数据库连接创建,释放频繁造成西戎资源的浪费,从而影响系统性能,使用数据库连接池可以解决问题。

2.sql语句在代码中硬编码,造成代码的不已维护,实际应用中sql的变化可能较大,sql代码和java代码没有分离开来维护不方便。

3.使用preparedStatement向有占位符传递参数存在硬编码问题因为sql中的where子句的条件不确定,同样是修改不方便/

4.对结果集中解析存在硬编码问题,sql的变化导致解析代码的变化,系统维护不方便。

mybatis对传统的JDBC的解决方案

1、数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。

解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接。

2、Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。

解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

3、向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。

解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。

4、对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。

解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

Mybaits整体体系图

0

0

一个Mybatis最简单的使用列子如下:

String resource = "mybatis-config.xml";
Reader reader;
try {
    //将XML配置文件构建为Configuration配置类             
    reader = Resources.getResourceAsReader(resource);             
    // 通过加载配置文件流构建一个SqlSessionFactory  
    DefaultSqlSessionFactory SqlSessionFactory
    sqlMapper = new SqlSessionFactoryBuilder().build(reader);             
    // 数据源 执行器  
    DefaultSqlSession SqlSession session = sqlMapper.openSession();
    try {                 
        // 执行查询 底层执行jdbc                 
        // User user = (User)session.selectOne("com.tuling.mapper.selectById", 1);                  
        UserMapper mapper = session.getMapper(UserMapper.class);
        System.out.println(mapper.getClass());
        User user = mapper.selectById(1L);
        System.out.println(user.getUserName());
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        session.close();
    }
} catch (IOException e) {
    e.printStackTrace();
}

总结下就是分为下面四个步骤:

  • 从配置文件(通常是XML文件)得到SessionFactory;
  • 从SessionFactory得到SqlSession;
  • 通过SqlSession进行CRUD和事务的操作;
  • 执行完相关操作之后关闭Session。

启动流程分析

String resource = "mybatis-config.xml"; 
//将XML配置文件构建为Configuration配置类 
reader = Resources.getResourceAsReader(resource); 
// 通过加载配置文件流构建一个SqlSessionFactory  DefaultSqlSessionFactory

通过上面代码发现,创建SqlSessionFactory的代码在SqlSessionFactoryBuilder中,进去一探究竟:

//整个过程就是将配置文件解析成Configration对象,然后创建SqlSessionFactory的过程
//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(Configuration config) {
    return new DefaultSqlSessionFactory(config);
}

下面我们看下解析配置文件过程中的一些细节。

先给出一个配置文件的列子:

<?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>
    <!--SqlSessionFactoryBuilder中配置的配置文件的优先级最高;config.properties配置文件的优先级次之;properties标签中的配置优先级最低 -->
    <properties resource="org/mybatis/example/config.properties">
      <property name="username" value="dev_user"/>
      <property name="password" value="F2Fa3!33TYyg"/>
    </properties>

    <!--一些重要的全局配置-->
    <settings>
    <setting name="cacheEnabled" value="true"/>
    <!--<setting name="lazyLoadingEnabled" value="true"/>-->
    <!--<setting name="multipleResultSetsEnabled" value="true"/>-->
    <!--<setting name="useColumnLabel" value="true"/>-->
    <!--<setting name="useGeneratedKeys" value="false"/>-->
    <!--<setting name="autoMappingBehavior" value="PARTIAL"/>-->
    <!--<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>-->
    <!--<setting name="defaultExecutorType" value="SIMPLE"/>-->
    <!--<setting name="defaultStatementTimeout" value="25"/>-->
    <!--<setting name="defaultFetchSize" value="100"/>-->
    <!--<setting name="safeRowBoundsEnabled" value="false"/>-->
    <!--<setting name="mapUnderscoreToCamelCase" value="false"/>-->
    <!--<setting name="localCacheScope" value="STATEMENT"/>-->
    <!--<setting name="jdbcTypeForNull" value="OTHER"/>-->
    <!--<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>-->
    <!--<setting name="logImpl" value="STDOUT_LOGGING" />-->
    </settings>

    <typeAliases>

    </typeAliases>

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!--默认值为 false,当该参数设置为 true 时,如果 pageSize=0 或者 RowBounds.limit = 0 就会查询出全部的结果-->
            <!--如果某些查询数据量非常大,不应该允许查出所有数据-->
            <property name="pageSizeZero" value="true"/>
        </plugin>
    </plugins>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://10.59.97.10:3308/windty"/>
                <property name="username" value="windty_opr"/>
                <property name="password" value="windty!234"/>
            </dataSource>
        </environment>
    </environments>

    <databaseIdProvider type="DB_VENDOR">
        <property name="MySQL" value="mysql" />
        <property name="Oracle" value="oracle" />
    </databaseIdProvider>

    <mappers>
        <!--这边可以使用package和resource两种方式加载mapper-->
        <!--<package name="包名"/>-->
        <!--<mapper resource="./mappers/SysUserMapper.xml"/>-->
        <mapper resource="./mappers/CbondissuerMapper.xml"/>
    </mappers>

下面是解析配置文件的核心方法:

try {
    //issue #117 read properties first
    //解析properties标签,并set到Configration对象中
    //在properties配置属性后,在Mybatis的配置文件中就可以使用${key}的形式使用了。
    propertiesElement(root.evalNode("properties"));

    //解析setting标签的配置
    Properties settings = settingsAsProperties(root.evalNode("settings"));
    //添加vfs的自定义实现,这个功能不怎么用
    loadCustomVfs(settings);

    //配置类的别名,配置后就可以用别名来替代全限定名
    //mybatis默认设置了很多别名,参考附录部分
    typeAliasesElement(root.evalNode("typeAliases"));

    //解析拦截器和拦截器的属性,set到Configration的interceptorChain中
    //MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
    //Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
    //ParameterHandler (getParameterObject, setParameters)
    //ResultSetHandler (handleResultSets, handleOutputParameters)
    //StatementHandler (prepare, parameterize, batch, update, query)
    pluginElement(root.evalNode("plugins"));

    //Mybatis创建对象是会使用objectFactory来创建对象,一般情况下不会自己配置这个objectFactory,使用系统默认的objectFactory就好了
    objectFactoryElement(root.evalNode("objectFactory"));
    objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
    reflectorFactoryElement(root.evalNode("reflectorFactory"));

    //设置在setting标签中配置的配置
    settingsElement(settings);

    //解析环境信息,包括事物管理器和数据源,SqlSessionFactoryBuilder在解析时需要指定环境id,如果不指定的话,会选择默认的环境;
    //最后将这些信息set到Configration的Environment属性里面
    environmentsElement(root.evalNode("environments"));

    //
    databaseIdProviderElement(root.evalNode("databaseIdProvider"));

    //无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。解析typeHandler。
    typeHandlerElement(root.evalNode("typeHandlers"));
    //解析Mapper
    mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
    throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}

0

上面解析流程结束后会生成一个Configration对象,包含所有配置信息,然后会创建一个SqlSessionFactory对象,这个对象包含了Configration对象。

简单总结

对于MyBatis启动的流程(获取SqlSession的过程)这边简单总结下:

  • SqlSessionFactoryBuilder解析配置文件,包括属性配置、别名配置、拦截器配置、环境(数据源和事务管理器)、Mapper配置等;解析完这些配置后会生成一个Configration对象,这个对象中包含了MyBatis需要的所有配置,然后会用这个Configration对象创建一个SqlSessionFactory对象,这个对象中包含了Configration对象;

这里解析的东西比较多,大致概况:会把所有的信息都解析到Configration对象中,比较简单不多介绍。

文档:MyBatis的二级缓存原理分析(请暂时关注解析缓存内容)

链接:http://note.youdao.com/noteshare?id=b97d399a65e31008fef704164d24c784&sub=wcp1596698664968348

文档:Mybatis解析动态sql原理分析

链接:http://note.youdao.com/noteshare?id=8b076e28061434f6693d99401d3ed400&sub=D948A34AA06045AEB7A01733A98A4C06

文档:Mybatis-设计模式总结.note

链接:http://note.youdao.com/noteshare?id=4975cd9e83f1e73e14a369598a232abe&sub=5D52C27921074712B1AB91C9A72455C0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/158257.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

面向面试学习,全网最齐全的软件测试面试题(含答案)

做测试的&#xff0c;我整理的真的很用心了&#xff0c;能找的新鲜面经都找了。 一面 1. 自我介绍 2. 面向对象的三种特性 集成用到了哪些特性 多态的具体使用场景 设计模式中的多态体现&#xff08;手撕&#xff09; 封装&#xff1a;将属性私有化&#xff1b;封装的意义&a…

Vue路由 replace属性 控制浏览记录不能前进或后退

默认是push模式 表示页面一直增加&#xff0c;用户可以操作返回上一个页面 replace 模式 <router-link replace :to"{path:/user,query:{ id:123,age:666 }} ">跳转用户</router-link><!--replace true表示浏览器不能后退浏览记录-->

视觉BEV基本原理和方案解析

BEV(Bird’s-Eye-View)是一种鸟瞰视图的传感器数据表示方法&#xff0c;它的相关技术在自动驾驶领域已经成了“标配”&#xff0c;纷纷在新能源汽车、芯片设计等行业相继量产落地。BEV同样在高德多个业务场景使用&#xff0c;例如&#xff1a;高精地图地面要素识别、车道线拓扑…

Attention Transformer

来源老师课件&#xff0c;方便以后复习。 课参考链接&#xff1a; http://jalammar.github.io/illustrated-transformer/ 之前的知识链接&#xff1a; 【知识链接】WGAN Transformer Vit Swin-Transformer Swin-Unet Res-Vit TransUNet MAE Bra ADDA 打分函数&#xff1a; 多头…

【413.等差数列划分】

目录 一、题目描述二、算法原理三、代码实现 一、题目描述 二、算法原理 三、代码实现 class Solution { public:int numberOfArithmeticSlices(vector<int>& nums) {int nnums.size();if(n<3) return 0;vector<int> dp(n);dp[2]dp[1]dp[0]0;if(nums[2]-nu…

【目标检测】基于yolov5的铝型材表面缺陷检测(附代码和数据集,Ubuntu或者Linux系统均可运行)

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。(专栏订阅用户订阅专栏后免费提供数据集和源码一份,超级VIP用户不在服务范围之内) 路虽远,行则将至;事虽难,做…

Nacos在Windows本地安装并启动教程

Nacos在Windows本地安装并启动教程 Nacos注册中心和Eureka是两种常见的服务注册与发现组件&#xff0c;它们在以下方面存在一些区别&#xff1a; 开源项目&#xff1a;Nacos是阿里巴巴开源的项目&#xff0c;而Eureka是Netflix开源的项目。 功能特性&#xff1a;Nacos在服务注册…

实验二 Python运算符和内置函数的使用《Python程序设计》实验指导书

实验二 Python运算符和内置函数的使用 一、实验目的和要求 &#xff08;一&#xff09;熟练掌握运算符的使用。 &#xff08;二&#xff09;熟练掌握内置函数的使用。 二、实验内容 &#xff08;一&#xff09;输入三角形的3个边长a、b、c&#xff0c;求三角形的面积area…

YOLO目标检测——机油泄露检测数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;机械设备维护、工业生产监控、环保监管等数据集说明&#xff1a;机油泄露检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富标签说明&#xff1a;使用lableimg标注软件标注&#xff0c;标注框质量高&#xff0c;含voc(xml)、co…

go语言 | 图解字节青训营抖音(一)

前言 本文大致介绍了本人及本人所在小组为第五届字节跳动青训营后端专场大项目需求 —— 「实现一个极简版抖音」的部分实现细节。 需求 本届后端青训营大项目要求实现一个极简版抖音的后端服务&#xff0c;该后端服务通过 HTTP 协议向已被设计好的前端 App 传递数据&#xf…

【漏洞复现】IP-guard WebServer 远程命令执行

漏洞描述 IP-guard是一款终端安全管理软件,旨在帮助企业保护终端设备安全、数据安全、管理网络使用和简化IT系统管理。互联网上披露IP-guard WebServer远程命令执行漏洞情报。攻击者可利用该漏洞执行任意命令,获取服务器控制权限。 免责声明 技术文章仅供参考,任何个人和…

Android平台 - APP备案

今年因 工业和信息化部 要求&#xff0c;Andorid各大厂商陆续发出通知&#xff0c;需要各应用公司及时进行app备案&#xff0c;如过期未进行备案则会被陆续下架&#xff01; 正好在统计Andorid各平台对于app备案时间节点要求&#xff0c;故此予以总结&#xff08;一切均已平台为…

亚马逊美国站CPC认证ASTM F963测试项目要求有哪些?

ASTM F963是美国材料和试验联合会&#xff08;ASTM&#xff09;制定的儿童玩具安全性的标准规范&#xff0c;专门针对儿童玩具产品的安全性进行了规定和要求。 ASTM F963标准的内容和要求包括&#xff1a; 1、物理机械性能&#xff1a;规定了玩具的物理机械性能要求&#xff0…

cocos3.4.2 2d射线检测 和 animation动画

2D的射线检测 ,注:目标必须有2d刚体和2d碰撞器 ,且项目设置内必须是这个物理系统 //起点位置let objs new Vec2(this.node.getWorldPosition().x, this.node.getWorldPosition().y);// 终点 let obje new Vec2(objs.x 100, objs.y);// 射线检测let results PhysicsSystem2…

Python入门简介及下载安装,超详细教学!

文章目录 一、Python简介&#xff1a;Python解释器的类型Python的运行机制1、查看 Python 版本2、第一个Python3.x程序3、Python 应用 二、Python安装&#xff08;windows&#xff09;1、下载2、安装步骤&#xff1a; 三、运行Python1、交互式解释器&#xff1a;扩展&#xff1…

(预热2024最新)Java毕业设计、课程设计参考题目(全网最新 共计800多个)

临近期末或是毕业季&#xff0c;计算及专业的童鞋们最头疼的要数为毕设、课设选题目&#xff0c;不能太老旧、也不能太新颖&#xff08;无参考案例&#xff09;&#xff0c;慕代码为大家整理了近两年设计选题&#xff0c;让你直接上手开始选&#xff0c;省去了冥思苦想。从过来…

echarts 实现分割型柱状图示例

该示例有如下几个特点&#xff1a; ①实现数据过多时滚动展示&#xff08;echarts 数据过多时展示滚动条-CSDN博客&#xff09; ②实现tooltip自定义样式&#xff08;echarts 实现tooltip提示框样式自定义-CSDN博客&#xff09; ③鼠标放置时柱状图颜色更改 代码如下&#xff…

Android Fragment 要你何用?2.0版本

作者&#xff1a;小鱼人爱编程 1. 老生常谈&#xff1a;为什么需要Fragment? 先看Activity、Fragment、View三者的关系&#xff1a; Activity 拥有生命周期&#xff0c;但是需要和AMS通信(跨进程)&#xff0c;比较臃肿。 View 不需要和AMS通信&#xff0c;但没有生命周期&…

Ubuntu18.04安装Moveit框架

简介 Moveit是一个由一系列移动操作的功能包组成的集成化开发平台,提供友好的GUI,是目前ROS社区中使用度排名前三的功能包,Moveit包含以下三大核心功能,并集成了大量的优秀算法接口: 运动学:KDL,Trac-IK,IKFast...路径规划:OMPL,CHMOP,SBPL..碰撞检测:FCL,PCD... 一、更新功…

【PIE-Engine 数据资源】中国叶面积指数(LAI)月度合成产品

文章目录 一、 简介二、描述三、波段四、示例代码运行结果参考资料 一、 简介 数据名称中国叶面积指数&#xff08;LAI&#xff09;月度合成产品时间范围2002-2021年空间范围全国数据来源航天宏图代码片段var images pie.ImageCollection(“EMDO/MODIS_MONTH_LAI_CHINA”) 二…