目录
- 一、数据持久化的概念及ORM(Object Relational Mapping “对象关系映射”)的原理
- 1.1 持久化
- 1.2 ORM(Object Relational Mapping)
- 1.3 ORM解决方案(包含四个部分)
- 二、MyBatis简介
- 2.1 简介
- 2.2 特点
- 2.3 MyBatis开发环境
- 2.4 MyBatis核心配置文件(mybatis-config.xml)
- 2.4.1 MyBatis核心配置文件——配置元素简要说明
- 2.4.2 MyBatis核心配置文件——完整的文件配置简述
- 2.4.3 MyBatis核心配置文件——配置properties元素
- 2.4.4 mappers元素
- 2.4.5 数据库信息配置文件(database.properties)
- 2.5 创建SQL映射文件(mapper.xml)
- 三、Java使用Mybatis框架
- 3.1 测试类测试使用——初次使用
- 3.2 整合Mybatis相同代码
- 3.3 关于SqlSessionFactory的说明
- 3.4 关于SqlSession的说明
- 3.5 MyBatis框架优缺点
- 3.6 以日志的方式输出结果信息(配置日志)
- 3.6.1 pom.xml文件的配置信息
- 3.6.2 日志信息的配置文件(log4j.properties)
- 四、详细说明XXXMapper.xml文件的书写
- 4.1 别名与Java类型映射
- 4.2 一般的增删改查数据库书写
- 4.3 复杂的多参数传参
- 4.3.1 多参数传参
- 4.3.2 通过Map实现多参数传参(或Java的实体类传参)
- 4.4 两表联查的返回值处理(resultMap)
- 4.4.1 初步认识resultMap
- 4.4.2 通过resultMap实现两表联查的返回值处理(一对多)
- 4.4.3 通过resultMap实现两表联查的返回值处理(一对一)
- 4.4.4 局部配置自动映射
- 五、关于缓存问题说明
- 5.1 Mybatis缓存
- 5.2 二级缓存的配置
- 5.3 缓存失效
- 六、动态SQL
- 6.1 实现动态SQL的主要元素
- 6.2 if元素
- 6.3 trim元素
- 6.4 where元素
- 6.5 set元素
- 6.6 choose(when、otherwise)元素
- 6.7 foreach元素
- 6.8 sql标签
- 七、拓展
一、数据持久化的概念及ORM(Object Relational Mapping “对象关系映射”)的原理
1.1 持久化
持久化是程序数据在瞬时状态和持久状态间转换的过程
1.2 ORM(Object Relational Mapping)
即对象 / 关系映射,是一种数据持久化技术。它在对象模型和关系型数据库之间建立起对应关系,并且提供了一种机制,通过JavaBean对象去操作数据库表中的数据。
编写程序的时候,以面向对象的方式处理数据
保存数据的时候,却以关系型数据库的方式存储
1.3 ORM解决方案(包含四个部分)
在持久化对象上执行基本的增、删、改、查操作
对持久化对象提供一种查询语言或者API
对象关系映射工具
提供与事务对象交互、执行检查、延迟加载以及其他优化功能
二、MyBatis简介
2.1 简介
官网:http://mybatis.org
MyBatis 本是Apache的一个开源项目iBatis, 2010年项目由Apache迁移到了Google Code,并且改名为MyBatis 。2013年11月迁移到GitHub。
MyBatis通过实体类和SQL语句之间建立映射关系,是半自动化的ORM框架,是一款优秀的基于Java的数据持久层框架。
2.2 特点
基于SQL语法,简单易学
能了解底层封装过程,内部通过JDBC访问数据库的操作
SQL语句封装在配置文件中,便于统一管理与维护,降低程序的耦合度
方便程序代码调试
2.3 MyBatis开发环境
- 创建Maven工程,导入MyBatis依赖的组件
- 编写MyBatis核心配置文件(mybatis-config.xml)
- 创建实体类-POJO
- 创建SQL映射文件(mapper.xml)
- 创建测试类
1.读取核心配置文件mybatis-config.xml
2.创建SqlSessionFactory对象,读取配置文件
3.创建SqlSession对象
4.调用mapper文件进行数据操作
pom.xml文件的配置说明
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
<!-- mybatis框架 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
2.4 MyBatis核心配置文件(mybatis-config.xml)
2.4.1 MyBatis核心配置文件——配置元素简要说明
configuration | 配置 | 说明 |
---|---|---|
properties | 可以配置在Java 属性配置文件中 | |
settings | 修改 MyBatis 在运行时的行为方式 | 是设置一些非常重要的设置选项,用来设置和改变MyBatis运行时的行为方式 |
typeAliases | 为 Java 类型命名一个别名(简称) | 配置类型别名,通过与MyBatis的SQL映射文件相关联,减少输入 多余的完整类名,以简化操作。 |
typeHandlers | 类型处理器 | |
objectFactory | 对象工厂 | |
plugins | 插件 | |
environments | 环境 | 表示配置MyBatis的多套运行环境,将SQL映射到多个不同的数据库上 子元素节点:environment,但是必须指定其中一个为默认运行环境(通过default指定) |
environment | 环境变量 | |
mappers | 映射器 | 映射器,定义SQL映射语句 须在配置中引用mapper映射文件 |
2.4.2 MyBatis核心配置文件——完整的文件配置简述
<?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>
<!-- 引入MySQL的properties配置文件
可以配置在Java 属性配置文件中 -->
<properties resource="database.properties"/>
<!-- 修改 MyBatis 在运行时的行为方式 -->
<settings>
<!-- 配置LOG4J日志接入 -->
<setting name="logImpl" value="LOG4J"/>
</settings>
<!-- 类型处理器 -->
<typeAliases>
<!-- 设定实体类映射 可以写单独的文件 也可以直接指向一个文件夹 -->
<package name="com.fileUpload.pojo"/>
</typeAliases>
<!-- MySQL配置映射信息 default设置默认选择,选择id为mysql的配置 -->
<environments default="mysql">
<!-- 被默认选择的配置 -->
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 映射mapper文件 -->
<mapper resource="mybatis/mapper/FilemanageMapper.xml"/>
</mappers>
</configuration>
2.4.3 MyBatis核心配置文件——配置properties元素
通过外部指定的方式,
即配置在典型的Java属性文件中(如:database.properties),实现动态配置
<properties resource="database.properties"/>
......
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
</dataSource>
直接配置为xml,
并使用这些属性对配置项实现动态配置
<properties>
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/smbms"/>
<property name="user" value="root"/>
<property name="password" value="123456"/>
</properties>
......
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
</dataSource>
若两种方式都有配置,那么通过外部指定的方式优先级高于直接配置为xml(resource属性值的优先级高于property子节点配置的值)
2.4.4 mappers元素
使用类资源路径获取资源
<!-- 将mapper映射文件加入到系统核心配置文件中 -->
<mappers>
<mapper resource="mybatis/mapper/FilemanageMapper.xml"/>
</mappers>
使用URL获取资源
<mappers>
<mapper url="file:///E:/sqlmappers/UserMapper.xml"/>
<mapper url="file:///E:/sqlmappers/ProviderMapper.xml"/>
</mappers>
2.4.5 数据库信息配置文件(database.properties)
# 驱动
driver=com.mysql.jdbc.Driver
# 数据库位置
url=jdbc:mysql://127.0.0.1:3306/fileupload
# 数据库账户
user=root
# 数据库密码
password=123456
2.5 创建SQL映射文件(mapper.xml)
元素/属性 | 含义 | 说明 |
---|---|---|
namespace | 对应Java接口文件(命名空间) | namespace和子元素的id联合保证唯一,区别不同的mapper 绑定DAO接口 namespace的命名必须跟某个接口同名 接口中的方法与映射文件中SQL语句id一一对应 |
id | 对应Java接口文件中的方法名 | 命名空间中唯一的标识符 接口中的方法与映射文件中的SQL语句id一一对应 |
resultType | 返回值类型 | SQL语句返回值类型的完整限定名或别名 |
parameterType | 传入参数类型 | 表示查询语句传入参数的类型的完全限定名和别名 支持基础数据类型和复杂数据类型 |
cache | 配置给定命名空间的缓存 | |
cache-ref | 从其他命名空间引用缓存配置 | |
resultMap | 用来描述数据库结果集和对象的对应关系 | |
sql | 可以重用的SQL块,也可以被其他语句引用 | |
insert | 映射插入语句 | |
update | 映射更新语句 | |
delete | 映射删除语句 | |
select | 映射查询语句 | |
flushCache | 将其设置为true,不论语句什么时候被调用,都会导致缓存被清空。默认值:false | |
useCache | 将其设置为true,将会导致本条语句的结果被缓存。默认值:true | |
timeout | 这个设置驱动程序等待数据库返回请求结果,并抛出异常时间的最大等待值。默认不设置(驱动自行处理) | |
fetchSize | 这是暗示驱动程序每次批量返回的结果行数 | |
statementType | STATEMENT,PREPARED或CALLABLE的一种。让MyBatis选择使用Statement,PreparedStatement或CallableStatement。默认值:PREPARED | |
resultSetType | FORWARD_ONLY 、SCROLL_SENSITIVE 、 SCROLL_INSENSITIVE中的一种。默认是不设置(驱动自行处理) |
String类型需要写为string
<?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">
<mapper namespace="com.fileUpload.mapper.FilemanageMapper">
<select id="selectPages" resultType="int">
select COUNT(1) from filemanage;
</select>
</mapper>
三、Java使用Mybatis框架
3.1 测试类测试使用——初次使用
String mybatisPath = "mybatis/mybatis-config.xml";
InputStream inputStream = null;
try {
// 1.加载mybatis配置文件
inputStream = Resources.getResourceAsStream(mybatisPath);
// 2.根据mybatis配置文件,创建生成SQlSession的factory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 3.创建真正要执行SQL语句的对象——————MybatisUtil
// 默认参数为false,表示关闭事务自动提交,true开启事务自动提交
SqlSession sqlSession = sqlSessionFactory.openSession();
// int count = sqlSession.selectOne("FilemanageMapper.selectPages");// 找到文件中的方法
FilemanageMapper filemanageMapper = sqlSession.getMapper(FilemanageMapper.class);
int count = filemanageMapper.selectPages();
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
3.2 整合Mybatis相同代码
在实际使用中,文件只需要加载一次,由SqlSessionFactory 创造一系列的SqlSession对象即可,而且创建的过程是相同的,此时可以写一个单独的类来处理
/**
* Mybatis工具类
*/
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory;
static {
String mybatisPath = "mybatis/mybatis-config.xml";
InputStream inputStream = null;
try {
// 1.加载mybatis配置文件
inputStream = Resources.getResourceAsStream(mybatisPath);
// 2.根据mybatis配置文件,创建生成SQlSession的factory对象
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public synchronized static SqlSession getSqlSession(){
if (sqlSessionFactory != null){
// 3.创建真正要执行SQL语句的对象——————MybatisUtil
// 默认参数为false,表示关闭事务自动提交,true开启事务自动提交
return sqlSessionFactory.openSession();
}
return null;
}
}
3.3 关于SqlSessionFactory的说明
SqlSessionFactory是每个MyBatis应用的核心
作用:创建SqlSession实例
作用域:Application
生命周期与应用的生命周期相同
单例:存在于整个应用运行时,并且同时只存在一个对象实例
3.4 关于SqlSession的说明
包含了执行SQL所需的所有方法
对应一次数据库会话,会话结束必须关闭
线程级别,不能共享
在SqlSession里可以执行多次SQL语句,但一旦关闭了SqlSession就需要重新创建
SqlSession的两种使用方式
- 通过SqlSession实例直接运行映射的SQL语句
- 基于Mapper接口方式操作数据
调用sqlSession.selectOne()执行查询操作
调用sqlSession.getMapper(Mapper.class)执行DAO接口方法来实现对数据的查询操作
3.5 MyBatis框架优缺点
优点
- 与JDBC相比,减少了50%以上的代码量
- 最简单的持久化框架,小巧并简单易学
- SQL代码从程序代码中彻底分离,可重用
- 提供XML标签,支持编写动态SQL
- 提供映射标签,支持对象与数据库的ORM字段映射
缺点
- SQL语句编写工作量大,对开发人员有一定要求
- 数据库移植性差
3.6 以日志的方式输出结果信息(配置日志)
3.6.1 pom.xml文件的配置信息
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
3.6.2 日志信息的配置文件(log4j.properties)
log4j.rootLogger=DEBUG,CONSOLE
log4j.logger.cn.smbms.dao=debug
log4j.logger.com.ibatis=debug
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=debug
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=debug
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug
log4j.logger.java.sql.ResultSet=debug
######################################################################################
# Console Appender \u65e5\u5fd7\u5728\u63a7\u5236\u8f93\u51fa\u914d\u7f6e
######################################################################################
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=debug
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern= [%p] %d %c - %m%n
四、详细说明XXXMapper.xml文件的书写
4.1 别名与Java类型映射
别名 | 映射的类型 |
---|---|
string | String |
byte | Byte |
long | Long |
short | Short |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
int | Integer |
integer | Integer |
arraylist | ArrayList |
map | Map |
hashmap | HashMap |
list | List |
collection | Collection |
iterator | Iterator |
decimal | BigDecimal |
bigdecimal | BigDecimal |
object | Object |
…… | …… |
4.2 一般的增删改查数据库书写
添加:参数为Filemanage的实体类对象,其中fileName、filePath是Filemanage的属性(增、删、改不需要指定返回值类型)
<insert id="fileUpload" parameterType="Filemanage">
insert filemanage(fileName, filePath) VALUES (#{fileName},#{filePath})
</insert>
查询:参数为int 返回值为Filemanage的实体类对象(查询需要指定返回值类型)
<select id="selectFile" parameterType="int" resultType="Filemanage">
select id, fileName from filemanage order by id desc limit #{index},5;
</select>
上述的添加查询在xml文件中与Java接口文件的对应关系
实例——删除:
<delete id="delete" parameterType="long">
delete from filemanage where id = #{id}
</delete>
实例——修改:
<update id="update" parameterType="long">
update filemanage set fileName = '新的名字' where id = #{id}
</update>
4.3 复杂的多参数传参
4.3.1 多参数传参
采用注解的方式区分不同参数,此时需要与注解对应,不在需要parameterType属性
xml文件中一个sql
<update id="update">
update filemanage set fileName = #{fileName} where id = #{id}
</update>
对应接口方法
int update(@Param("id")long id, @Param("fileName")String name);
4.3.2 通过Map实现多参数传参(或Java的实体类传参)
xml文件中一个sql
<update id="update" parameterType="map">
update filemanage set fileName = #{fileName} where id = #{id}
</update>
对应接口方法
int update(Map<String, Object> maps);
Map的key必须与#{}中的内容对应
4.4 两表联查的返回值处理(resultMap)
4.4.1 初步认识resultMap
resultType :直接表示返回类型
- 基本数据类型
- 复杂数据类型
resultMap :对外部resultMap的引用
应用场景:
- 数据库字段信息与对象属性不一致
- 复杂的联合查询,自由控制映射结果
二者不能同时存在,本质上都是Map数据结构
resultMap自动映射匹配前提:字段名与属性名一致
resultMap的自动映射级别-autoMappingBehavior
- PARTIAL(默认):自动匹配所有,内部嵌套除外(就是在一个实体类中包含另一个实体类)
- NONE:禁止自动匹配
- FULL:自动匹配所有
实例——内部嵌套
public class Filemanage {
private long id;
private String fileName;
private String filePath;
private User user; // 这个就属于内部嵌套,无法使用resultMap默认的匹配方式匹配
}
<settings>
<setting name="autoMappingBehavior" value="NONE"/>
</settings>
resultMap 的属性:id(resultMap的唯一标识)type(Java实体类)
resultMap子元素:
名称 | 说明 |
---|---|
id | 一般对应数据库中该行的主键id,设置此项可提高MyBatis性能 |
result | 映射到JavaBean的某个“简单类型”属性 |
association | 映射到JavaBean的某个“复杂类型”属性(一对一),比如JavaBean类 |
collection | 映射到JavaBean的某个“复杂类型”属性(一对多),比如集合 |
<resultMap type="Filemanage" id="list">
<result property="id" column="id"/>
<result property="fileName" column="fileName"/>
<result property="filePath" column="filePath"/>
</resultMap>
<select id="getFilemanageList" resultMap="list">
select id, fileName, filePath from filemanage;
</select>
4.4.2 通过resultMap实现两表联查的返回值处理(一对多)
public class Filemanage {
private long id;
private String fileName;
private String filePath;
private List<User> userList;
}
resultMap 内部引用(不推荐,不适用于复用)
<resultMap type="Filemanage" id="list">
<id property="id" column="id"/>
<result property="fileName" column="fileName"/>
<result property="filePath" column="filePath"/>
<collection property="userList" ofType="User">
<!-- 此处的id在查询语句中有了别名,此处需要改为别名使用,以防重复 -->
<result property="id" column="userid"/>
<result property="userName" column="userName"/>
<result property="age" column="age"/>
<result property="sex" column="sex"/>
</collection>
</resultMap>
<select id="getFilemanageList" resultMap="list" parameterType="long">
select id, fileName, filePath, userName, age, sex, u.id userid
from filemanage f join user u on f.id = u.fileId
where f.id = #{id};
</select>
resultMap 外部引用
<resultMap type="Filemanage" id="list">
<id property="id" column="id"/>
<result property="fileName" column="fileName"/>
<result property="filePath" column="filePath"/>
<!-- 外部引用 -->
<collection property="userList" resultMap="userlist"/>
</resultMap>
<resultMap id="userlist" type="User">
<!-- 此处的id在查询语句中有了别名,此处需要改为别名使用,以防重复 -->
<result property="id" column="userid"/>
<result property="userName" column="userName"/>
<result property="age" column="age"/>
<result property="sex" column="sex"/>
</resultMap>
<select id="getFilemanageList" resultMap="list" parameterType="long">
select id, fileName, filePath, userName, age, sex, u.id userid
from filemanage f join user u on f.id = u.fileId
where f.id = #{id};
</select>
4.4.3 通过resultMap实现两表联查的返回值处理(一对一)
public class Filemanage {
private long id;
private String fileName;
private String filePath;
private User user;
}
resultMap 内部引用(不推荐,不适用于复用)
<resultMap type="Filemanage" id="list">
<id property="id" column="id"/>
<result property="fileName" column="fileName"/>
<result property="filePath" column="filePath"/>
<association property="userList" ofType="User">
<!-- 此处的id在查询语句中有了别名,此处需要改为别名使用,以防重复 -->
<result property="id" column="userid"/>
<result property="userName" column="userName"/>
<result property="age" column="age"/>
<result property="sex" column="sex"/>
</association>
</resultMap>
<select id="getFilemanageList" resultMap="list" parameterType="long">
select id, fileName, filePath, userName, age, sex, u.id userid
from filemanage f join user u on f.id = u.fileId
where f.id = #{id};
</select>
resultMap 外部引用
<resultMap type="Filemanage" id="list">
<id property="id" column="id"/>
<result property="fileName" column="fileName"/>
<result property="filePath" column="filePath"/>
<!-- 外部引用 -->
<association property="userList" resultMap="user"/>
</resultMap>
<resultMap id="user" type="User">
<!-- 此处的id在查询语句中有了别名,此处需要改为别名使用,以防重复 -->
<result property="id" column="userid"/>
<result property="userName" column="userName"/>
<result property="age" column="age"/>
<result property="sex" column="sex"/>
</resultMap>
<select id="getFilemanageList" resultMap="list" parameterType="long">
select id, fileName, filePath, userName, age, sex, u.id userid
from filemanage f join user u on f.id = u.fileId
where f.id = #{id};
</select>
4.4.4 局部配置自动映射
<resultMap type="Filemanage" id="list">
<id property="id" column="id"/>
<result property="fileName" column="fileName"/>
<result property="filePath" column="filePath"/>
<!-- 外部引用 -->
<association property="userList" resultMap="user"/>
</resultMap>
<!-- 配置了局部的自动映射!!! -->
<resultMap id="user" type="User" autoMapping="true">
<!-- 此处的id在查询语句中有了别名,此处需要改为别名使用,以防重复 -->
<result property="id" column="userid"/>
<result property="userName" column="userName"/>
<result property="age" column="age"/>
<result property="sex" column="sex"/>
</resultMap>
<select id="getFilemanageList" resultMap="list" parameterType="long">
select id, fileName, filePath, userName, age, sex, u.id userid
from filemanage f join user u on f.id = u.fileId
where f.id = #{id};
</select>
五、关于缓存问题说明
5.1 Mybatis缓存
在ORM框架中引入缓存的目的就是为了减少读取数据库的次数,从而提升查询的效率。
Mybatis默认开启一级缓存,不能关闭
Mybatis默认关闭二级缓存
一级缓存是SqlSession级别的缓存,随其开启而开启,关闭而关闭。也就是在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中;第二次以后是直接去缓存中取。
一级缓存的范围有SESSION和STATEMENT两种,默认是SESSION,如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除
二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存,此后若再次执行相同的查询语句,结果就会从缓存中获取
5.2 二级缓存的配置
MyBatis的全局cache配置
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
在Mapper XML文件中设置缓存,默认情况下是没有开启缓存的
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
在Mapper XML文件配置支持cache后,如果需要对个别查询进行调整,可以单独设置cache
<select id="selectAll" resultType="Emp" useCache="true">
5.3 缓存失效
缓存失效:
- sqlSession不同,缓存失效。
- sqlSession相同,查询条件不同,缓存失效,因为缓存中可能还没有相关数据。
- sqlSession相同,在两次查询期间,执行了增删改操作,缓存失效。
- sqlSession相同,但是手动清空了一级缓存,缓存失效。
清除缓存情况:
- 就是获取缓存之前会先进行判断用户是否配置了flushCache=true属性(参考一级缓存的创建代码截图),
如果配置了则会清除一级缓存。 - MyBatis全局配置属性localCacheScope配置为Statement时,那么完成一次查询就会清除缓存。
- 在执行commit,rollback,update方法时会清空一级缓存
二级缓存失效:
- 所有的update操作(insert,delete,uptede)都会触发缓存的刷新,从而导致二级缓存失效,所以二级缓存适合在读多写少的场景中开启。
- 二级缓存针对的是同一个namespace,所以建议是在单表操作的Mapper中使用,或者是在相关表的Mapper文件中共享同一个缓存。
相关解读:MyBatis一级缓存和二级缓存
六、动态SQL
6.1 实现动态SQL的主要元素
if、trim、where、set、choose(when、otherwise)、foreach
6.2 if元素
<if test='条件判断语句(推荐使用单引号)'>
正确的语句拼接
</if>
<select id="getUserList" resultType="User">
select u.*,r.roleName as userRoleName
from smbms_user u,smbms_role r
where u.userRole = r.id
<if test='userName != null and userName != ""'>
and u.userName like concat('%',#{userName},'%')
</if>
<if test='userRole != null and userRole != 0'>
and u.userRole = #{userRole}
</if>
order by creationDate DESC limit #{currentPageNo},#{pageSize}
</select>
6.3 trim元素
属性:prefix、suffix、prefixOverrides、suffixOverrides
可以用来替代where和set
prefix:需要添加的前缀
prefixOverrides:属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容。
suffixOverrides:删除最后一个指定的内容
suffix:在最后添加的语句
<update id ="mode" parameterType="User">
update smbms
<trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
<if test="userCode != null">userCode = #{userCode},</if>
<if test="userName!= null">userCode = #{userName },</if>
<if test="userPassword!= null">userPassword=#{userPassword },</if>
</trim>
</update>
<select id="selectNotificDynamic1" resultType="com.wex.entity.Notific">
SELECT * FROM Notific
<trim prefix="where" prefixOverrides="and |or">
<if test="method != null">
and Method = #{method,jdbcType=VARCHAR}
</if>
<if test="statusOfread != null">
and StatusOfread = #{statusOfread,jdbcType=VARCHAR}
</if>
</trim>
</select>
6.4 where元素
<where>
此处填写where后面的语句,where元素可以自动添加where
</where>
<select id="getProviderList" resultType="Provider">
select * from smbms_provider
<where>
<if test='proName != null and proName != ""'>
and proName like concat('%',#{proName},'%')
</if>
<if test='proCode != null and proCode != ""'>
and proCode like concat('%',#{proCode},'%')
</if>
</where>
</select>
当where中所有的if都是false且where中没有其他语句时,where会自动不添加
优化了select * from smbms_provider where 1 = 1 的情况,省略了1 = 1
6.5 set元素
<update id="modify" parameterType="Provider">
update smbms_provider
<set>
<if test='proName != null'>
proName=#{proName},
</if>
<if test='proDesc != null'>
proDesc=#{proDesc},
</if>
<if test='proContact != null'>
proContact=#{proContact},
</if>
</set>
where id = #{id}
</update>
6.6 choose(when、otherwise)元素
相当于Java中switch语句
当when有条件满足的时候,就跳出choose
<choose>
<when test ="条件1"> …</when>
<when test ="条件2"> …</when>
<when test ="条件3"> …</when>
…
<otherwise>…</otherwise>
</choose>
6.7 foreach元素
属性:item、index、collection必须指定(list、array、map-key)、open、separator、close
对应接口
public interface BillMapper {
public Provider selectById(ArrayList<String> arrayList);
}
实际的sql语句
select * from smbms_provider where id in (参数1,参数2,参数3…);
采用foreach完成这个sql语句
- item别名
- collection传入数据类型
- open开始
- separator间隔
- close结尾
<select id="selectById" parameterType="string" resultType="Provider">
select *
from smbms_provider
<where>
id in
<foreach collection="array" item="userId" open="(" separator="," close=")">
#{arrayList}
</foreach>
</where>
</select>
6.8 sql标签
sql标签中的内容可以被多次引用,达到重复使用的目的
<sql id="timesql">
proName,proDesc
</sql>
<select id="time" resultType="Provider">
select id,<include refid="timesql"/> from smbms_provider
</select>
七、拓展
在mapper的接口文件中可以这样书写
public interface BillMapper {
@Select("select COUNT(1) from smbms_provider")
public int selectCount();
}