前言:
小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java半年多时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。
这个Mybatis基础学习系列是用来记录我学习Mybatis框架基础知识的全过程 (这个系列是参照B站狂神的Mybatis最新教程来写的,由于是之前整理的,但当时没有发布出来,所以有些地方可能有错误,希望大家能够及时指正!)
之后我将尽量以一天一更的速度更新这个系列,还没有学习Mybatis3框架的小伙伴可以参照我的博客学习一下;当然学习过的小伙伴,也可以顺便跟我一起复习一下基础。最后,希望能够和大家一同进步吧!加油吧!少年们!
特别提醒:如果对Mybatis基础学习系列感兴趣,可以阅读本系列往期博客:
第一篇:Mybatis基础学习之初识Mybatis
第二篇:Mybatis基础学习之第一个Mybatis程序
第三篇:Mybatis基础学习之CRUD增删改查
第四篇:Mybatis基础学习之万能的Map和模糊查询
由于Mybatis基础学习之配置解析的内容比较多,所以这里我将其拆分为上下两篇来发布。上篇主要介绍Mybatis核心配置中的环境配置、事务管理器、数据源、属性和类型别名等内容;下篇主要介绍设置、其他配置和映射器,以及Mybatis的生命周期等。
上篇博客地址链接:Mybatis基础学习之配置解析(上篇)
今天我们来到了Mybatis基础学习的第五站:配置解析(下篇),主要内容就是能。废话不多说,让我们开始今天的学习内容吧。
5.7 设置(setting)
这是MyBatis中极为重要的调整设置,它们会改变MyBatis的运行时行为
5.7.1 常用设置的含义及默认值
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关 (当开启后,所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态) | true | false | false |
useColumnLabel | 使用列标签代替列名 (实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察) | true | false | true |
useGeneratedKeys | 允许JDBC支持自动生成主键,需要数据库驱动支持。如果设置为true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如Derby) | true|false | false |
autoMappingBehavior | 指定MyBatis应如何映射列到字段或属性 (NONE表示关闭自动映射;PARTIAL只会自动映射到没有定义嵌套结果映射的字段;FULL会自动映射任何复杂的结果集) | NONE|PARTIAL|FULL | PARTIAL |
mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射 (即从经典数据库列名 (例如last_name) 映射到经典Java属性名(例如LastName) ) | true | false | false |
logImpl | 指定MyBatis所用日志的具体实现,未指定时将自动查找 | SLF4J | LOG4J | …(省略部分见下方提醒)… | NO_LOGGING | 未设置 |
localCacheScope | MyBatis利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询 (默认值为Session:会缓存一个会话中执行的所有查询;若设置为Statement:本地缓存将仅用于执行语句,对相同SqlSession的不同查询将不会进行缓存) | Session|Statement | Session |
jdbcTypeForNull | 当没有为参数指定特定的JDBC类型时,空值的默认JDBC类型 (某些数据库驱动需要指定列的JDBC类型,多数情况直接使用一般类型即可,比如Null、Varchar、Other) | JdbcType常量,常用值:Null、Varchar或Other | Other |
lazyLoadTriggerMethods | 指定对象的哪些方法触发一次延迟加载 | 用逗号分隔的方法列表 | equals,clone,hashCode,toString |
特别提醒:
设置名为logImpl的有效值主要包括SLF4J|LOG4J|LOG4J2|JDK_LOGGINGCOMMONS_LOGGING|STDOUT_LOGGING|NO_LOGGING
5.7.2 配置完整setting元素实例
<settings>
<!-- 全局性地开启(所有映射配置文件中)已配置的任何缓存 -->
<setting name="cacheEnabled" value="true"/>
<!-- 开启所有关联对象的延迟加载(懒加载) -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 允许单个语句返回多结果集 -->
<setting name="multipleResultSetsEnabled" value="true"/>
<!-- 使用列标签代替类名 -->
<setting name="useColumnLabel" value="true"/>
<!-- 是否允许JDBC支持自动生成主键, 默认值为false: 表示不支持自动生成主键 -->
<setting name="useGeneratedKeys" value="false"/>
<!-- 指定MyBatis自动映射没有定义嵌套结果映射的字段(默认值为PARTIAL) -->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<!-- 指定发现自动映射目标未知列(或未知属性类型)的行为,设置值为WARNING: 表示输出警告日志 -->
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<!-- 配置默认的执行器,设置值为SIMPLE:表示普通的执行器 -->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!-- 设置超时时间,它决定数据库驱动等待数据库响应的秒数(可设置为任意正整数), 这里设置的是25秒 -->
<setting name="defaultStatementTimeout" value="25"/>
<!-- 为驱动的结果集获取数量(fetchSize)设置一个建议值(可设置为任意正整数)。此参数只可以在查询设置中被覆盖 -->
<setting name="defaultFetchSize" value="100"/>
<!-- 是否允许在嵌套语句中使用分页(RowBounds), 默认值为false: 表示允许使用 -->
<setting name="safeRowBoundsEnabled" value="false"/>
<!-- 是否开启驼峰命名自动映射, 默认值为false: 表示开启。例如, 经典数据库列名: last_name映射到经典Java属性名: LastName -->
<setting name="mapUnderscoreToCamelCase" value="false"/>
<!-- MyBatis利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询, 默认值为SESSION: 会缓存一个会话中执行的所有查询 -->
<setting name="localCacheScope" value="SESSION"/>
<!-- 当没有为参数指定特定的JDBC类型时, 空值的默认JDBC类型。某些数据库驱动需要指定列的JDBC类型,多数情况直接使用一般类型即可,比如Null、Varchar、Other -->
<setting name="jdbcTypeForNull" value="OTHER"/>
<!-- 指定对象的哪些方法触发一次延迟加载: 用逗号分隔的方法列表 -->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
5.8 其他配置
-
typeHandler(类型处理器)
-
objectFactory(对象工厂)
-
plugins(插件)
MyBatis Generator Core:会自动生成增删改查过程(逆向工程),但是可有时能会出现一些问题
MyBatis Plus:MyBatis的增强工具(为简化而生)通用Mapper
5.9 映射器(mappers)
5.9.1 映射器的四种使用方式
- 什么是MapperRegistry?
MapperRegistry:注册绑定Mapper配置文件
1.使用相对于类路径的资源引用
- 使用相对于类路径的资源引用 (即使用resource资源路径绑定注册),推荐使用!
<!-- 每一个Mapper.xml都需要再Mybatis核心配置文件中注册 -->
<mappers>
<mapper resource="com/kuang/dao/UserMapper.xml"/>
</mappers>
2.使用完全限定资源定位符
- 使用完全限定资源定位符 (即使用URL链接绑定注册) ,不推荐使用,url路径容易出错!
<mappers>
<mapper url="file:///resources/mapper/UserMapper.xml"/>
</mappers>
3.使用映射器接口实现类的完全限定名
- 使用映射器接口实现类的完全限定名 (即使用class文件绑定注册),可以使用,工作中用的会很多,但可能会受mapper配置文件存放位置的影响!
<mappers>
<mapper class="com.kuang.dao.UserMapper"/>
</mappers>
4.将包内的映射器接口实现全部注册为映射器
- 将包内的映射器接口实现全部注册为映射器 (即扫描package包绑定注册)
<mappers>
<package name="com.kuang.dao"/>
</mappers>
5.9.2 使用相对于类路径的资源引用
简单理解就是使用resource资源路径绑定注册
1.设置mapper配置文件存放位置
2.编写 mybatis-config.xml 配置文件
2-1使用resources/mapper/UserMapper.xml路径
<?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>
<!-- 引入外部配置文件 -->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="pwd" value="111111"/>
</properties>
<!-- 通过包起别名 -->
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
<!-- 设置默认环境为开发环境 -->
<environments default="development">
<!-- 设置一道环境为开发环境 -->
<environment id="development">
<!-- transactionManager: 事务管理器,MyBatis的默认管理器是JDBC -->
<transactionManager type="JDBC"/>
<!-- 数据源作用: 连接数据库,MyBatis的默认数据源类型是POOLED,也就是有池的连接 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${pwd}"/>
</dataSource>
</environment>
</environments>
<!-- 使用相对于类路径的资源引用(使用resource资源路径绑定注册) -->
<mappers>
<mapper resource="resources/mapper/UserMapper.xml"/>
</mappers>
</configuration>
2-2 使用mapper/UserMapper.xml路径
<?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>
<!-- 引入外部配置文件 -->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="pwd" value="111111"/>
</properties>
<!-- 通过包起别名 -->
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
<!-- 设置默认环境为开发环境 -->
<environments default="development">
<!-- 设置一道环境为开发环境 -->
<environment id="development">
<!-- transactionManager: 事务管理器,MyBatis的默认管理器是JDBC -->
<transactionManager type="JDBC"/>
<!-- 数据源作用: 连接数据库,MyBatis的默认数据源类型是POOLED,也就是有池的连接 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${pwd}"/>
</dataSource>
</environment>
</environments>
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
3.编写 UserMapper.xml 映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace=绑定一个对应的Dao/Mapper接口 -->
<mapper namespace="com.kuang.dao.UserMapper">
<!-- select查询语句:select的id属性,要和接口中定义的方法名相同
通过包起别名后,resultType(结果类型)直接使用对应实体类(使用时注意首字母小写) -->
<select id="getUserList" resultType="user">
select * from mybatis.user
</select>
</mapper>
4.编写 UserDaoTest 测试类
public class UserDaoTest {
@Test
public void test(){
//获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
//使用getMapper方法来获取接口对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用getUserList方法,查询所有用户
List<User> userList = userMapper.getUserList();
//遍历数组
for (User user : userList) {
System.out.println(user);
}
}catch(Exception e){
e.printStackTrace();
}finally {
//关闭sqlSession
sqlSession.close();
}
}
}
5.测试结果
5-1.使用 resources/mapper/UserMapper.xml 路径
报错:通过resources/mapper/UserMapper.xml路径找不到资源
结论:因此,这个路径格式显然不正确
5-2.使用mapper/UserMapper.xml路径
结果:查询用户列表信息成功!
结论:因此,在使用相对于类路径的资源引用时要注意路径绑定是否正确!
5.9.3 使用映射器接口实现类的完全限定名
简单理解就是使用class文件绑定注册
1.设置mapper配置文件存放位置
1-1 存放在resources文件目录下
1-2 存放在dao文件目录下
2.编写 mybatis-config.xml 配置文件
<?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>
<!-- 引入外部配置文件 -->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="pwd" value="111111"/>
</properties>
<!-- 通过包起别名 -->
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
<!-- 设置默认环境为开发环境 -->
<environments default="development">
<!-- 设置一道环境为开发环境 -->
<environment id="development">
<!-- transactionManager: 事务管理器,MyBatis的默认管理器是JDBC -->
<transactionManager type="JDBC"/>
<!-- 数据源作用: 连接数据库,MyBatis的默认数据源类型是POOLED,也就是有池的连接 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${pwd}"/>
</dataSource>
</environment>
</environments>
<!-- 使用映射器接口实现类的完全限定名(即使用class文件绑定注册) -->
<mappers>
<mapper class="com.kuang.dao.UserMapper"/>
</mappers>
</configuration>
3.编写mapper配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace=绑定一个对应的Dao/Mapper接口 -->
<mapper namespace="com.kuang.dao.UserMapper">
<!-- select查询语句:select的id属性,要和接口中定义的方法名相同
注意: 虽然使用通过包起别名, 但mappers映射器使用的是class文件绑定, 因此这里的返回类型User类首字母仍要大写 -->
<select id="getUserList" resultType="User">
select * from mybatis.user
</select>
</mapper>
4.编写 UserDaoTest 测试类
public class UserDaoTest {
@Test
public void test(){
// 获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
// 使用getMapper方法来获取接口对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 调用getUserList方法,查询所有用户
List<User> userList = userMapper.getUserList();
// 遍历数组
for (User user : userList) {
System.out.println(user);
}
} catch(Exception e){
e.printStackTrace();
} finally {
// 关闭sqlSession
sqlSession.close();
}
}
}
5.测试结果
5-1 存放在resources文件目录下
报错:无效的绑定语句,未找到com.kuang.dao. usermaper . getuserlist
5-2 存放在dao文件目录下
6.测试结论
在使用映射器接口实现类的完全限定名(即使用class文件绑定注册)的情况下,不建议将mapper配置文件存放在resource目录下(即mapper接口与配置文件不在同一位置),因此mapper配置文件应该与mapper接口应该在同一位置 (即存放在同一文件目录下)
简单总结,即为两点:
- 接口与它的Mapper配置文件必须同名!
- 接口与它的Mapper配置文件必须在同一个包下!
5.9.4 将包内的映射器接口实现全部注册为映射器
简单理解就是扫描package包进行绑定注册
1.设置mapper配置文件存放位置
2.编写 mybatis-config.xml 配置文件
<?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>
<!-- 引入外部配置文件 -->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="pwd" value="111111"/>
</properties>
<!-- 通过包起别名 -->
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
<!-- 设置默认环境为开发环境 -->
<environments default="development">
<!-- 设置一道环境为开发环境 -->
<environment id="development">
<!-- transactionManager: 事务管理器, MyBatis的默认管理器是JDBC -->
<transactionManager type="JDBC"/>
<!-- 数据源作用: 连接数据库, MyBatis的默认数据源类型是POOLED, 也就是有池的连接 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${pwd}"/>
</dataSource>
</environment>
</environments>
<!-- 将包内的映射器接口实现全部注册为映射器(扫描package包绑定注册) -->
<mappers>
<package name="com.kuang.dao"/>
</mappers>
</configuration>
3.编写mapper配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace=绑定一个对应的Dao/Mapper接口 -->
<mapper namespace="com.kuang.dao.UserMapper">
<!-- 通过包起别名后,resultType(结果类型)直接使用对应实体类(使用时注意首字母小写) -->
<select id="getUserList" resultType="user">
select * from mybatis.user
</select>
</mapper>
4.编写 UserDaoTest 测试类
public class UserDaoTest {
@Test
public void test(){
// 获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
// 使用getMapper方法来获取接口对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 调用getUserList方法,查询所有用户
List<User> userList = userMapper.getUserList();
// 遍历数组
for (User user : userList) {
System.out.println(user);
}
} catch(Exception e){
e.printStackTrace();
} finally {
// 关闭sqlSession
sqlSession.close();
}
}
}
5.测试结果
6.拓展测试
6-1 修改接口名称
- 将UserMapper接口改为UserDao接口,使mapper接口与配置文件不同名
6-2 测试结果
报错:无效的绑定语句,未找到com.kuang.dao. usermaper . getuserlist
6-3 测试结论
因此在使用将包内的映射器接口实现全部注册为映射器时(即使用package包名绑定注册),需要注意mapper接口与mapper配置文件名称应保持一致!
7.测试总结
- 接口与它的Mapper配置文件必须同名!
- 接口与它的Mapper配置文件必须在同一个包下!
5.10 生命周期和作用域
生命周期和作用域是至关重要的,因为错误的使用会导致非常严重的并发问题!
5.10.1 Mybatis的生命周期执行流程图
5.10.2 简单解析生命周期各部分
1.简单解析SqlSessionFactoryBuilder
SqlSessionFactoryBuilder一旦创建了SqlSessionFactory,就不再需要它了,并且它属于局部变量
2.简单解析SqlSessionFactory
SqlSessionFactory相当于数据库连接池,一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
SqlSessionFactory最佳实践是应用的运行期间不要重复创建多次,因此其最佳作用域是应用作用域。最简单的就是使用单例模式或者静态单例模式。
3.简单解析SqlSession
SqlSession表示连接到连接池的一个请求。SqlSession的实例不是线程安全的,因此是不能被共享的。所以它的最佳作用域是请求或者方法作用域
注意:用完之后要赶紧关闭,否则资源被占用!
4.SqlSessionFactory和SqlSession联系
注意:这里面的每一个Mapper,就代表一个具体的业务
好了,今天的有关 配置解析(下篇) 的学习就到此结束啦。欢迎小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连。我们下期见,拜拜啦!
参考视频链接:https://www.bilibili.com/video/BV1NE411Q7Nx?spm_id_from=333.999.0.0(【狂神说Java】Mybatis最新完整教程IDEA版通俗易懂)