深入理解MyBatis的原理(三):配置文件(上)
前言:前文提到一个入门的demo,从这里开始,会了解深入 MyBatis 的配置,本文讲解 MyBatis 的配置文件的用法。
目录
1、properties 元素
2、设置(settings)
3、别名(typeAliases)
配置 XML 文件的层次结构
<?xml version="1.0" encoding="UTF-8"?> <configuration><!--配置--><properties/><!--属性--><settions/><!--设置--><typeAliases/><!--类型命名,不区分大小写--><typeHandlers/><!--类型处理器--><objectFactory/><!--对象工厂--><plugins/><!--插件--><environments><!--配置环境--><environment><transactionManager/><!--事务管理器--><dataSource/><!--数据源--></environment></environments><databaseIdProvider/><!--数据库厂商标识--><mappers/><!--映射器--> </configuration>
注意:MyBatis 配置 XML 文件的层次结构。这些层次是不能够颠倒顺序的,如果颠倒顺序,MyBatis 在解析 XML 文件的时候就会出现异常。
xml 为什么不能颠倒顺序
至于为什么不能颠倒顺序,是由于 MyBatis3 是使用 dtd 文件作为 xml 文件的格式校验的,而在 xml 规范中,dtd 是有严格校验顺序的。
在 idea 中,如果颠倒顺序,idea 会提示下图信息:
查看源码可以得知,在 org/apache/ibatis/builder/xml/mybatis-3-config.dtd 文件中,有明确定义该顺序:
1、properties 元素
properties 是一个配置属性的元素,让我们能够在配置文件的上下文中(其他配置属性里面,比如环境配置)使用它。
我们可以有 3 种配置方式:property 子元素、properties 配置文件、程序的参数传递。
1.1、property 子元素
dtd 的规则
配置好后在数据库环境配置里使用
<!--属性,property 子元素--><properties><property name="driver" value="oracle.jdbc.OracleDriver"/><property name="datasourceurl" value="jdbc:oracle:thin:@localhost:1521:ORCL"/><property name="username" value="testdev"/><property name="password" value="test1234"/></properties><!--配置环境--><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${datasourceurl}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments>
1.2 properties 配置文件
经常,我们都喜欢使用 properties 配置文件来配置属性值,方便我们在多个配置文件中重复使用,更是为了方便系统上线后的维护和修改。
dtd 的规则
建一个 db.properties 文件
driver=oracle.jdbc.OracleDriver datasourceurl=jdbc:oracle:thin:@localhost:1521:ORCL username=testdev password=test1234
配置文件
<properties resource="config/system/db.properties"/><!--配置环境--><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${datasourceurl}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments>
1.3 程序参数传递
有时,我们的数据库名和密码不对开发公布,而是由运维人员配置的,所以这是数据库名和密码可以加密配置在 db.properties 文件中,然后由程序去 decode,创建 sqlSessionFactory 时采用 SqlSessionFactoryBuilder 的 public SqlSessionFactory build(Reader reader, Properties roperties) 方法。
程序部分代码如下
/*** 初始化sqlSessionFactory,针对数据库的密码和用户名加密的情况* @throws IOException*/public void initSqlSessionFactoryForEncodeDbInfo() throws IOException {//读入配置文件流InputStream inputStream = Resources.getResourceAsStream("configuration.xml");Reader reader = new InputStreamReader(inputStream);//读入属性文件Reader propertiesReader = new InputStreamReader(Resources.getResourceAsStream("config/system/db.properties"));Properties properties = new Properties();properties.load(propertiesReader);//解密properties.setProperty("username", decode(properties.get("username")));properties.setProperty("password", decode(properties.get("password")));sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader, properties);}
1.4 优先级
方法参数传递的属性优先级最高,次之是 resource/url 属性中的配置,最后是 property 中的属性。
但是在实际中最好使用 properties 文件的配置方式。
2、设置(settings)
settings 比较复杂,也很重要,它会改变 MyBatis 运行时的行文。不配置 settings,MyBatis也可以正常工作。
大部分情况下,我们都可以不去配置 settings,或者只需修改几个配置即可。
设置参数 | 描述 | 有效值 | 默认值 |
cacheEnabled | 该配置影响的所有映射器中配置的缓存的全局开关 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态 | true | false | false |
aggressiveLazyLoading | 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载。 | true | false | true |
multipleResultSetsEnabled | 是否允许单一语句返回多结果集(需要兼容驱动)。 | true | false | true |
useColumnLabel | 使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 | true | false | true |
useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 | true | false | False |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库响应的秒数。 | Any positive integer | Not Set (null) |
defaultFetchSize | Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a query setting. | Any positive integer | Not Set (null) |
safeRowBoundsEnabled | 允许在嵌套语句中使用分页(RowBounds)。 | true | false | False |
mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 | true | false | False |
localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
lazyLoadTriggerMethods | 指定哪个对象的方法触发一次延迟加载。 | A method name list separated by commas | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定动态 SQL 生成的默认语言。 | A type alias or fully qualified class name. | org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver |
callSettersOnNulls | 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 | true | false | false |
logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | Any String | Not set |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | Not set |
proxyFactory | 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 or above) |
3、别名(typeAliases)
别名是一个指代的名称。可以在 MyBatis 的上下文中使用。
在 MyBatis 中别名是不分大小写的。
一个 typeAliases 的实例是在解析配置文件时(源码在 XMLConfigBuilder 中)生成的,然后长期保存在 Configuration 对象中,当我们使用它时,再把它拿出来,这样就没有必要运行时再次生成它的实例了。
别名分为系统定义别名和自定义别名。
3.1 为什么 MyBatis 中别名是部分大小写的
因为源码 org.apache.ibatis.type.TypeAliasRegistry 如下:
public void registerAlias(String alias, Class<?> value) {if(alias == null) {throw new TypeException("The parameter alias cannot be null");} else {String key = alias.toLowerCase(Locale.ENGLISH);if(this.TYPE_ALIASES.containsKey(key) && this.TYPE_ALIASES.get(key) != null && !((Class)this.TYPE_ALIASES.get(key)).equals(value)) {throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + ((Class)this.TYPE_ALIASES.get(key)).getName() + "'.");} else {this.TYPE_ALIASES.put(key, value);}}}
3.2 系统定义别名
MyBatis 自己有定义一些常用的别名,我们可以直接使用它们,不用自己定义,也不要再使用时重复定义把它们给覆盖了。
支持数组类型的只要加“[]”即可。比如 Integer 数组,则别名为 int[]。
别名 | Java类型 | 是否支持数组 |
_byte | byte | y |
_long | long | y |
_short | short | y |
_int | int | y |
_integer | int | y |
_double | double | y |
_float | float | y |
_boolean | boolean | y |
string | String | y |
byte | Byte | y |
long | Long | y |
short | Short | y |
int | Integer | y |
integer | Integer | y |
double | Double | y |
float | Float | y |
boolean | Boolean | y |
date | Date | y |
decimal | BigDecimal | y |
bigdecimal | BigDecimal | y |
object | Object | y |
map | Map | n |
hashmap | HashMap | n |
list | List | n |
arraylist | ArrayList | n |
collection | Collection | n |
iterator | Iterator | n |
ResultSet | ResultSet |
n |
源码 org.apache.ibatis.type.TypeAliasRegistry 中可以看出其自定义注册的信息,源码如下:
public TypeAliasRegistry() {this.registerAlias("string", String.class);this.registerAlias("byte", Byte.class);this.registerAlias("long", Long.class);this.registerAlias("short", Short.class);this.registerAlias("int", Integer.class);this.registerAlias("integer", Integer.class);this.registerAlias("double", Double.class);this.registerAlias("float", Float.class);this.registerAlias("boolean", Boolean.class);this.registerAlias("byte[]", Byte[].class);this.registerAlias("long[]", Long[].class);this.registerAlias("short[]", Short[].class);this.registerAlias("int[]", Integer[].class);this.registerAlias("integer[]", Integer[].class);this.registerAlias("double[]", Double[].class);this.registerAlias("float[]", Float[].class);this.registerAlias("boolean[]", Boolean[].class);this.registerAlias("_byte", Byte.TYPE);this.registerAlias("_long", Long.TYPE);this.registerAlias("_short", Short.TYPE);this.registerAlias("_int", Integer.TYPE);this.registerAlias("_integer", Integer.TYPE);this.registerAlias("_double", Double.TYPE);this.registerAlias("_float", Float.TYPE);this.registerAlias("_boolean", Boolean.TYPE);this.registerAlias("_byte[]", byte[].class);this.registerAlias("_long[]", long[].class);this.registerAlias("_short[]", short[].class);this.registerAlias("_int[]", int[].class);this.registerAlias("_integer[]", int[].class);this.registerAlias("_double[]", double[].class);this.registerAlias("_float[]", float[].class);this.registerAlias("_boolean[]", boolean[].class);this.registerAlias("date", Date.class);this.registerAlias("decimal", BigDecimal.class);this.registerAlias("bigdecimal", BigDecimal.class);this.registerAlias("biginteger", BigInteger.class);this.registerAlias("object", Object.class);this.registerAlias("date[]", Date[].class);this.registerAlias("decimal[]", BigDecimal[].class);this.registerAlias("bigdecimal[]", BigDecimal[].class);this.registerAlias("biginteger[]", BigInteger[].class);this.registerAlias("object[]", Object[].class);this.registerAlias("map", Map.class);this.registerAlias("hashmap", HashMap.class);this.registerAlias("list", List.class);this.registerAlias("arraylist", ArrayList.class);this.registerAlias("collection", Collection.class);this.registerAlias("iterator", Iterator.class);this.registerAlias("ResultSet", ResultSet.class);}
View Code
3.3 自定义别名
(1)在配置文件中写法如下
<!--定义别名--><typeAliases><typeAlias type="com.yule.user.entity.User" alias="user"/></typeAliases>
(2)或者当实体类较多的时候,使用自动扫描的形式自定义别名
<!--定义别名--><typeAliases> <package name="com.yule.user.entity"/></typeAliases>
同时也可以在实体类上使用注解 @Alias
@Alias("user") public class User {//do somethings }
注意:如果配置了包扫描的路径,那么没有在实体上加注解 @Alias 的类也在装载在 MyBatis 的上下文中,只是 MyBatis 将类名的第一个字母变为小写,作为 MyBatis 上下文中的别名,所以要特别注意避免重名的情况,建议使用部分包名+类名的限定。
转载于:https://www.cnblogs.com/yuxiaole/p/9463120.html
深入理解MyBatis的原理(三):配置文件(上)相关推荐
- MyBatis运行原理(三)接口式编程及创建代理对象原理分析
一.面向接口开发步骤 定义代理接口,将操作数据库的方法定义在代理接口中. 在SQL 映射文件中编写SQL 语句. 将SQL 映射文件注册在MyBatis 的全局配置文件中. 编写测试代码. 二.环境准 ...
- 深入理解MyBatis的原理(四):映射器的用法
前言:继续深入学习 mybatis 的用法及原理,还是先会用再学习原理. 映射器的主要元素有:select.insert.update.delete.parameterMap(即将被删除,不建议使用) ...
- 《深入理解mybatis原理三》 Mybatis数据源与连接池
对于ORM框架而言,数据源的组织是一个非常重要的一部分,这直接影响到框架的性能问题.本文将通过对MyBatis框架的数据源结构进行详尽的分析,并且深入解析MyBatis的连接池. 本文首先会讲述MyB ...
- MyBatis版本升级引发的线上告警回顾及原理分析
本文从一次MyBatis版本升级引发的线上告警开始讲起,然后针对告警定位过程.源码原理进行了深入的分析,并加入了不同版本的类比分析,最后结合实际工作做了一些经验总结,希望能对大家的工程实践有一定的帮助 ...
- mybatis 传入id_想深入理解MyBatis架构及原理实例分析 把握这些就够了
前言 MyBatis是目前非常流行的ORM框架,它的功能很强大,然而其实现却比较简单.优雅.本文主要讲述MyBatis的架构设计思路,并且讨论MyBatis的几个核心部件,然后结合一个select查询 ...
- 深入理解mybatis原理, Mybatis初始化SqlSessionFactory机制详解(转)
文章转自http://blog.csdn.net/l454822901/article/details/51829785 对于任何框架而言,在使用前都要进行一系列的初始化,MyBatis也不例外.本章 ...
- mybatis 原理_深入理解MyBatis原理 MyBatis数据源与连接池
点击上方"程序开发者社区"关注,选择"设为星标" 第一时间送达实用干货 对于ORM框架而言,数据源的组织是一个非常重要的一部分,这直接影响到框架的性能问题.本文 ...
- 《深入理解mybatis原理》 MyBatis的架构设计以及实例分析
MyBatis是目前非常流行的ORM框架,它的功能很强大,然而其实现却比较简单.优雅.本文主要讲述MyBatis的架构设计思路,并且讨论MyBatis的几个核心部件,然后结合一个select查询实例, ...
- mysql主从复制原理详解_MySQL主从复制没使用过?三大步骤让你从原理、业务上理解透彻...
成长是一棵树,总是在你不知不觉的情况下快乐长大:成长是一株草,总是在你不知不觉的情况下长满大地:成长是一朵花,总是在你不知不觉的情况下开满山头. 这不,随着时间的迁移.项目网站的用户量.数据量持续上升 ...
最新文章
- 谷歌开源预训练新范式BiT,准确率提高近25%!网友评价:CV界的BERT
- Linux 小知识翻译 - 「NTP」
- 现代程序设计 学生情况调查
- Linux 进程 | 进程间的通信方式
- linux后台停止执行命令,Linux 命令的后台运行
- Deepin添加PPA显示没有公钥签名
- Takeown 实现解析
- ubuntu 16.04 创建新用户
- 10个最新优秀手机应用界面设计实例
- python语言程序设计西安电子科技大学答案-中国科学技术大学2019自命题科目覆盖范围及参考书目...
- limesurvey的问卷类型
- php是一种通用开源,caozha-admin(PHP网站后台管理框架)
- NVIDIA显卡驱动报错
- qq空间上传html代码,100分!如何在博客或msn、qq空间里面添加html代码?
- FPGA学习-PS2接口
- 大数据技术怎么自学?大数据开发如何自学?
- python兔子繁殖问题
- python线程锁和线程池
- 博图V14完美自动化程序案例
- 一个域名价值怎么看 域名估值的标准是什么