MyBatis总结(2)- MyBatis实现原理(二)

核心配置

  • Mybatis-config.xml(基础配置)

作用

Mybatis-config.xml实现:

  1. 这在前面说过,加载解析都是在Configuration对象被创建时发生:
    org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration:
private void parseConfiguration(XNode root) {
    try {
      // issue #117 read properties first
      propertiesElement(root.evalNode("properties"));
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      loadCustomVfsImpl(settings);
      loadCustomLogImpl(settings);
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginsElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlersElement(root.evalNode("typeHandlers"));
      mappersElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }
  1. 一个基础简单配置定义:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	
    <properties resource="db.properties"/>

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <typeAliases>
        <package name="org.example.pojo"/>
    </typeAliases>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper class="org.example.daos.UserMapper"/>
            <mapper class="org.example.daos.TeacherMapper"/>
            <mapper class="org.example.daos.StudentMapper"/>
        </mappers>

    </configuration>

具体配置标签使用

这是官网的参考链接:Mybatis配置定义
在这里,将知识转化成自己的方式理解,这才是学到了。
以下是按照自己的理解总结:

Properties

定义配置属性,一般用在对DataSource参数的设置上:

  1. 针对不同地方定义属性值的代码实现:
  • 使用java.util.Properties,put存放数值利用ConcurrentHashMap的不可重复特性,覆盖去重;
  • 加载resource/url资源配置时,通过properties #load方法直接转化,对原始转化做了个完美的语法糖:
		...
		// 原始基础原理:一步步的,先读取到缓冲字节区域buffer,然后经由buffer再写入/处理
		// 这里的buffer,我理解成:“倒爷”
		InputStream inputStream = getClass().getResourceAsStream(filePath);
        ServletOutputStream outputStream = response.getOutputStream();
        byte[] buffer = new byte[1024];
        int lens;
        while((lens = inputStream.read(buffer))> 0){
            outputStream.write(buffer, 0, lens);
        }
        ...
  • 关闭资源时,可以用try-resources语句,针对实现了AutoCloseable接口的资源类,程序会在使用完资源后后台自动帮忙关闭。
  1. 具体实现:
<!-- Properties标签: URL|Resource(只能二选一)
        resource 属性读取**类路径**下属性文件;
        url 属性**指定的路径**读取属性文件
        properties设置有三种途径(按照优先级高低):
            方法参数(builder.build(..., props)) >>>> url | resource定义的配置属性 >>>> properties标签下定义的属性
            
    -->
    <!--例子1:
    	引入外部properties文件,设置全部属性 ${} -->
    <properties resource="db.properties"/>读取类路径下的资源
    <properties url=""/>URL:可以是网络资源,也可以本地服务器资源

    <!--例子2:
    	引入外部properties文件,设置部分属性 ${}-->
        <properties resource="db1.properties">
            <property name="user" value="root"/>
            <property name="pwd" value="root"/>
        </properties>

    <!--例子3:
    	引入外部properties文件,设置部分属性,当属性key一致时,优先使用properties外部资源的属性 ${}-->
    <properties resource="db.properties">
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=true
"/>
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
    </properties>

Setting

针对Mybatis一些行为的设置,记住常用的几个,其他的,用的时候查阅参考链接即可:

<settings>
		<!--指定日志的具体实现:	
		STDOUT_LOGGING:  -->
    <setting name="logImpl" value="STDOUT_LOGGING"/>标准日志输出,一般用在本地调试,可在console中查看代码的执行过程
    <setting name="logImpl" value="LOG4J2"/>可通过log4j2配置文件定制化日志文件

		<setting name="mapUnderscoreToCamelCase" value="true"/>开启驼峰映射:Column(a_b)映射为属性(aB)
</settings>

typeAliases

一个目的:起别名。简化在mapper映射关系中,指定type时,可以简化。一般会为了省掉包名,只用类名来表示。
当然针对,类名可能存在一致的问题(多module开发),那就加上包名来以示区别。

<typeAliases><!--两种方式-->
        <!--给具体的一个javabean起别名 -->
        <typeAlias type="org.example.pojo.User" alias="User"/>
        <!--通过扫描pojo包来设置别名:默认javabean别名为类名的首字母小写 @Alias("user"),也可以在javabean上指定别名通过注解@Alias -->
        <package name="org.example.pojo"/>当前包下的所有bean,就会起效
    </typeAliases>

应用于mapper.xml中:

<select id="getUserById" resultType="org.example.pojo.User">这里的org.example.pojo.User可以简化为User/user
    SELECT * FROM mybatis.user where id = #{id}
</select>

typeHandlers

  • 在从ResultSet结果集中获取值时,会用到类型处理器来做转化操作,例如:SqlDateTypeHandlerStringTypeHandler等;
  • 也可自定义实现:重写已有类型处理器,或实现TypeHandler接口,或继承BaseTypeHandler类,参考官网链接。

Plugins

这里提一下,在追代码时看到,在handler处理器处理某个逻辑时,会有一处代码:

interceptorChain.pluginAll(xxx)
这就是plugin的作用之处:利用Mybatis自定义的拦截器Interceptor,在逻辑处理前后增添自定义功能

Environment

每个数据库对应一个SqlSessionFactory实例,每个SqlSessionFactory实例只能选一种环境:

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>
  • ID: 可以设置dev,test,SIT,UAT,Stage,Prod等多个环境的配置;
  • TransactionManager:type有两种:MANAGED(默认),JDBC
  • datasource:数据源配置:UNPOOLED | POOLED | JNDI(内建的三种数据源类型),还可通过实现DataSourceFactory,扩展C3P0,DBCP,Druid.

mappers

这是涉及到下一个核心的SQL映射关系的引入:

<mappers>
    <mapper resource="mappers/user-mappers.xml"/> <!--通过资源resource导入-->
    <mapper class="org.example.daos.UserMapper"/> 通过class方式注入
    <package name="org.example.daos"/>通过package扫描注入
</mappers>

这里需要注意的是,对于将mapper配置放在src/main/java目录下的不能加载问题,第一篇初探有提到过。

总而言之,到这里会发现,(个人感慨)

  • Mybatis做的精明之处就是在于将我们原本复杂的逻辑通过config配置,在经过factory的构建,整合成一个SqlSession给到我们,我们只需要关注到业务的实现,底层的技术细节帮我们处理好了。

  • 除过Mybatis内置的功能外,还给提供了很多对外扩展的接口,比如:
    TypeHandler,plugin, DataSourceFactory, TransactionFactory&Transaction等等。

  • 学习最好的方式就是看源码,根据内置的实现,模仿着去实现自定义,就能理解其中道理;

  • 所以,技术框架的迭代,万变不离其宗,而且技术没有高低之分

  • 后面,总结Spring会发现这种扩展性的接口会更多,也为学习更多的架构层面的策略,以及技术的掌握提供很好的途径。

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值