核心配置
- Mybatis-config.xml(基础配置)
作用
Mybatis-config.xml实现:
- 这在前面说过,加载解析都是在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);
}
}
- 一个基础简单配置定义:
<?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参数的设置上:
- 针对不同地方定义属性值的代码实现:
- 使用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接口的资源类,程序会在使用完资源后后台自动帮忙关闭。
- 具体实现:
<!-- 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会发现这种扩展性的接口会更多,也为学习更多的架构层面的策略,以及技术的掌握提供很好的途径。