MyBatis-核心配置文件mybatis-config.xml主要参数详解
创始人
2024-02-14 03:45:03

1.全局配置文件

全局配置文件,见名知意就是对当前MyBatis的一些全局属性进行设置。也就是对各种数据操作进行统一规定。
全局配置文件包含了全局设置(setting)和properties两个大的部分,通过这两个大的部分动态的影响MyBatis的行为。下面我从几个方面去介绍:
大致来看看最简单的全局配置文件:



......

但是,上面各个标签的顺序,我绝对不是随便给的。MyBatis对各个标签的顺序有规定。
如果标签的顺序不正确,会出现错误,如下图:

在这里插入图片描述
核心配置文件中的标签必须按照固定的顺序(有的标签可以不写,但顺序一定不能乱):
properties、settings、typeAliases、typeHandlers、objectFactory、objectWrapperFactory、reflectorFactory、plugins、environments、databaseIdProvider、mappers

那我就按照上述的顺序来将一些常见的进行介绍:

2、properties: 通过配置文件动态绑定值

表名的是可外部化,可替换的一些属性。在典型的JAVA属性中配置他们文件的实例。比如jdbc.properties文件的导入。

[jdbc.properties]

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3307/mybatis
jdbc.username=root
jdbc.password=admin

然后,我们就可以在数据源中动态的设置这些值。


2. setting :对全局设置相关属性值

是在mybatis运行过程中修改运行行为一个非常重要的方式。其中规定了很多属性的值,如是否开启全局缓存,懒加载是否开启等等.
我只截取其中的一部分,其他详细的请查阅相关文档。

2.1 cacheEnabled

结论:cachedEnable这个开关实际上控制的上创建executor(用来处理sql的)的类型,创建的executor取决于defaultExecutorType默认是SimpleExecutor这个类是没有二级缓存功能的,如果cachedEnable是true(默认),就会使用CachingExecutor对SimpleExecutor包装。CachingExecutor这个是具有二级缓存功能的。

   public Executor newExecutor(Transaction transaction, ExecutorType executorType) {// 获得执行器类型executorType = executorType == null ? defaultExecutorType : executorType; // 使用默认executorType = executorType == null ? ExecutorType.SIMPLE : executorType; // 使用 ExecutorType.SIMPLE// 创建对应实现的 Executor 对象Executor executor;if (ExecutorType.BATCH == executorType) {executor = new BatchExecutor(this, transaction);} else if (ExecutorType.REUSE == executorType) {executor = new ReuseExecutor(this, transaction);} else {executor = new SimpleExecutor(this, transaction);}// 如果开启缓存,创建 CachingExecutor 对象,进行包装if (cacheEnabled) {executor = new CachingExecutor(executor);}// 应用插件executor = (Executor) interceptorChain.pluginAll(executor);return executor;}

所以cachedEnable=false二级缓存就被关闭了,但是cachedEnable=true仅仅是使用了CachingExecutor,不能代表使用了二级缓存,因为CachingExecutor使用了Cache对象缓存数据,只有在Mapper中配置标签,解析的时候才会有Cache对象,否则还是不会用到二级缓存的。

(二级坑比较多,用的人也很少)

2.2 启用延迟加载和按需加载

懒加载针对什么使用的?为什么要用懒加载?
懒加载针对级联使用的,懒加载的目的是减少内存的浪费和减轻系统负担。
懒加载是什么?
你可以理解为按需加载,当我调用到关联的数据时才与数据库交互否则不交互。
再具体点来说:
比如user表和role表有关联关系,有这样一条语句:查询uesr的同时将user的某一列数据作为参数一并查询role表符合条件的数据,mybatis里叫做级联。只要执行这条语句,就会将这两张表符合需求的信息一起加载出来。而懒加载只会加载uesr表的数据出来不加载role表的数据。
还不懂怎么办?
将下面的代码敲一遍,不要做任何的调用只运行下面的方法:

 public void testFindAll(){users = userDao.findAll();
}

至于为什么下面你将会知道。
如何使用开启懒加载?
在mybatis的主配置文件的Setings标签开启。



注意:标签的顺序,必须位于properties之后typeAliases之前。如果位置错乱会导致mybatis启动失败。
注意:这个是开启全局的懒加载开关。
lazyLoadingEnabled默认为false。
aggressiveLazyLoading 3.4.1(包含)前为true,之后为false。
开启懒加载一定要两个属性都配置吗?
不是的,真正开启懒加载标签的只是lazyLoadingEnabled:true表示开启,false表示关闭,默认为false。
如果我不想将全部的级联都设计懒加载怎么办?
association和collection有个fetchType属性可以覆盖全局的懒加载状态:eager表示这个级联不使用懒加载要立即加载,lazy表示使用懒加载。
注意:discriminator没有fetchType属性,因此它只能随大众不能有自己的小九九。


鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为 封装Employee
如果查出的是女生 : 就把部门信息查询出来,否则不查询
如果是男生 : 把username这一列的值赋值给email




既然fetchType可以控制懒加载那么我仅仅配置fetchType不配置全局的可以吗?
可以的。
aggressiveLazyLoading是做什么么的?
它是控制具有懒加载特性的对象的属性的加载情况的。
true表示如果对具有懒加载特性的对象的任意调用会导致这个对象的完整加载,false表示每种属性按照需要加载。
还是不懂怎么办?
看具体效果:

两个接口:

public interface IRole {List findAll();List findById(String id);
}
public interface IUser {List findAll();
}

两个实体类:

public class Role implements Serializable {private String id;private String userId;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}@Overridepublic String toString() {return "Role{" +"id='" + id + '\'' +", userId='" + userId + '\'' +'}';}
}public class User implements Serializable {private  String id;private  List role;private String name ;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {name = "丽华";return name;}public void setName(String name) {this.name = name;}public List getRole() {return  role;}public void setRole(List role) {this.role = role;}@Overridepublic String toString() {return "User{" +"id='" + id + '\'' +'}';}
}

三个配置文件:














两个表:
role表:
在这里插入图片描述

在这里插入图片描述
这里简单描述一下;
uesr和role的关系为一对多。开启了全局懒加载。
并且在user的配置中配置级联,那么称user的实例为带有懒加载属性的对象。
aggressiveLazyLoading的属性为false,即每种属性按需加载,不调用就不加载。
运行测试方法:

 @Testpublic void testFindAll(){users = userDao.findAll();for(User user : users){System.out.println("-----每个用户的信息------");System.out.println(user.getName());}}

结果:

2019-11-26 19:37:21,627 128    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Opening JDBC Connection
2019-11-26 19:37:22,323 824    [           main] DEBUG source.pooled.PooledDataSource  - Created connection 793138072.
2019-11-26 19:37:22,326 827    [           main] DEBUG  com.itheima.dao.IUser.findAll  - ==>  Preparing: select * from user 
2019-11-26 19:37:22,347 848    [           main] DEBUG  com.itheima.dao.IUser.findAll  - ==> Parameters: 
2019-11-26 19:37:22,400 901    [           main] DEBUG  com.itheima.dao.IUser.findAll  - <==      Total: 4
-----每个用户的信息------
丽华
-----每个用户的信息------
丽华
-----每个用户的信息------
丽华
-----每个用户的信息------
丽华
2019-11-26 19:37:22,401 902    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2f465398]
2019-11-26 19:37:22,401 902    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 793138072 to pool.

可以看到只执行user的sql语句,并且只加载调用的属性并没有加载 private List role;

下面将aggressiveLazyLoading设置为true:只要对这个类的任意操作将完整加载整个类的所有属性即执行级联的SQL语句
运行同样的测试方法:

2019-11-26 19:35:33,893 123    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Opening JDBC Connection
2019-11-26 19:35:34,597 827    [           main] DEBUG source.pooled.PooledDataSource  - Created connection 793138072.
2019-11-26 19:35:34,600 830    [           main] DEBUG  com.itheima.dao.IUser.findAll  - ==>  Preparing: select * from user 
2019-11-26 19:35:34,621 851    [           main] DEBUG  com.itheima.dao.IUser.findAll  - ==> Parameters: 
2019-11-26 19:35:34,677 907    [           main] DEBUG  com.itheima.dao.IUser.findAll  - <==      Total: 4
-----每个用户的信息------
2019-11-26 19:35:34,678 908    [           main] DEBUG com.itheima.dao.IRole.findById  - ==>  Preparing: select * from role where user_id=? 
2019-11-26 19:35:34,679 909    [           main] DEBUG com.itheima.dao.IRole.findById  - ==> Parameters: 1(String)
2019-11-26 19:35:34,680 910    [           main] DEBUG com.itheima.dao.IRole.findById  - <==      Total: 2
丽华
-----每个用户的信息------
2019-11-26 19:35:34,680 910    [           main] DEBUG com.itheima.dao.IRole.findById  - ==>  Preparing: select * from role where user_id=? 
2019-11-26 19:35:34,680 910    [           main] DEBUG com.itheima.dao.IRole.findById  - ==> Parameters: 2(String)
2019-11-26 19:35:34,681 911    [           main] DEBUG com.itheima.dao.IRole.findById  - <==      Total: 2
丽华
-----每个用户的信息------
2019-11-26 19:35:34,681 911    [           main] DEBUG com.itheima.dao.IRole.findById  - ==>  Preparing: select * from role where user_id=? 
2019-11-26 19:35:34,681 911    [           main] DEBUG com.itheima.dao.IRole.findById  - ==> Parameters: 4(String)
2019-11-26 19:35:34,682 912    [           main] DEBUG com.itheima.dao.IRole.findById  - <==      Total: 0
丽华
-----每个用户的信息------
2019-11-26 19:35:34,682 912    [           main] DEBUG com.itheima.dao.IRole.findById  - ==>  Preparing: select * from role where user_id=? 
2019-11-26 19:35:34,682 912    [           main] DEBUG com.itheima.dao.IRole.findById  - ==> Parameters: 5(String)
2019-11-26 19:35:34,683 913    [           main] DEBUG com.itheima.dao.IRole.findById  - <==      Total: 3
丽华
2019-11-26 19:35:34,684 914    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2f465398]
2019-11-26 19:35:34,684 914    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 793138072 to pool.

我们只调用了getName方法没有调用getRole方法但mybatis却调用了查询role的语句。
现在可以更明确aggressiveLazyLoading的作用了:
true:
只要调用任意具有懒加载特性的对象的任意一个属性将完整加载整个对象,即触发级联效果。
false:
只加载调用的属性,不调用的属性不加载。
还是不懂怎么办?
将上面的过程自己来一遍。
还有一个问题,如果我仅仅使用aggressiveLazyLoading不使用lazyLoadingEnabled还有能按需加载吗?即调用getName不执行role的sql语句,就像第一种情况那样
如果不开启懒加载,在执行user的sql语句时也将执行role的sql语句。因此不能实现需求。

2.3 multipleResultSetsEnabled

一条sql 对应多个结果集,resultMap 多个

2.4、useColumnLabel

确切的说当映射找不到参数时会使用列标签(数据库列名)代替别名去映射

3. typeAliases( alias,package) 设置类型的别名

设置别名:为一些比较长的类名起一个比较短的代称。
里面有的属性有
type: 需要设置别名的全类型名。
alias: 设置此类型的别名,并且不进行区分大小写 ,如果这项不进行设定的话,框架给一个默认的别名——以类名作为别名。



但是,对于开发中,这种操作一般比较繁琐。一般使用扫描包的方式来做。通过以包为单位,设置和修改包下的所有类都拥有默认的别名(即是类名),并且所有的别名都不区分大小写。

系统中默认配置的别名:

在这里插入图片描述

4. environments:设置数据库环境

用于设置多个连接数据库的环境。比如说一些其他数据库,Oracle,MySQL等等,在需要的使用达到动态切换的目的。
而对于要使用哪个环境,是通过default属性来设置对应environment的id来实现的。
一个environments有很多的environment,但是只能有一个作为项目的数据库环境。

 

4.1 transactionManager:设置事务管理方式

属性:type=“JDBC/MANAGED”

JDBC: 在当前环境中,执行sql时,使用的是jdbc原生的事务管理方式,需要手动的提交和回滚事务
MANAGED:被管理,例如Spring

5. mappers:引入映射文件

mappers引入映射文件有三种方式(严格来说是四种)。而这里博主只介绍一种常用的方式:🍒以包围单位引入配置文件

但是,以包为单位引入配置文件,有两个要求:

mapper接口所在的包要和映射文件所在的包要一致。
mapper接口要和映射文件的名称一致。
满足了上述两个要求之后,就可以在标签内利用标签实现批量引入映射文件。

 

Notice:还有一个需要注意的点,在resources中,如果一次性创建多个层级目录,不能使用如图所示,使用.来创建。而要使用com/fangshaolei/mybatis/mapper才能创建出和类包一样的目录结构。
否则会报:BindingException: Type interface com.atguigu.mybatis.mapper.UserMapper is not known to the MapperRegistry.

6.总结

本节内容,没有什么特殊的tips,对于还有一些其他的配置信息,可以在MyBatis官方文档中有详细说明,博主不在班门弄斧的解释。

一份完整的mybatis-config.xml配置示例:



 

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...