[框架]Mybatis的使用

news2024/11/19 18:32:44

目录

  • 一、数据持久化的概念及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对象去操作数据库表中的数据。
编写程序的时候,以面向对象的方式处理数据
保存数据的时候,却以关系型数据库的方式存储

ORM图示说明

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开发环境

  1. 创建Maven工程,导入MyBatis依赖的组件
  2. 编写MyBatis核心配置文件(mybatis-config.xml)
  3. 创建实体类-POJO
  4. 创建SQL映射文件(mapper.xml)
  5. 创建测试类
    1.读取核心配置文件mybatis-config.xml
    2.创建SqlSessionFactory对象,读取配置文件
    3.创建SqlSession对象
    4.调用mapper文件进行数据操作
MyBatis依赖的组件
org.mybatis mybatis
mysql mysql-connector-java
junit junit
log4j log4j

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映射文件

在这里插入图片描述

environment 环境变量
transactionManager 事务管理器
dataSource 数据源

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这是暗示驱动程序每次批量返回的结果行数
statementTypeSTATEMENT,PREPARED或CALLABLE的一种。让MyBatis选择使用Statement,PreparedStatement或CallableStatement。默认值:PREPARED
resultSetTypeFORWARD_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 测试类测试使用——初次使用

build方法
openSession方法
SqlSessionFactoryBuilder
SqlSessionFactory
SqlSession
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的两种使用方式

  1. 通过SqlSession实例直接运行映射的SQL语句
  2. 基于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类型映射

别名映射的类型
stringString
byteByte
longLong
shortShort
doubleDouble
floatFloat
booleanBoolean
dateDate
intInteger
integerInteger
arraylistArrayList
mapMap
hashmapHashMap
listList
collectionCollection
iteratorIterator
decimalBigDecimal
bigdecimalBigDecimal
objectObject
…………

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接口文件的对应关系

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

  1. PARTIAL(默认):自动匹配所有,内部嵌套除外(就是在一个实体类中包含另一个实体类)
  2. NONE:禁止自动匹配
  3. 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>

初步认识resultMap

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 缓存失效

缓存失效:

  1. sqlSession不同,缓存失效。
  2. sqlSession相同,查询条件不同,缓存失效,因为缓存中可能还没有相关数据。
  3. sqlSession相同,在两次查询期间,执行了增删改操作,缓存失效。
  4. sqlSession相同,但是手动清空了一级缓存,缓存失效。

清除缓存情况:

  1. 就是获取缓存之前会先进行判断用户是否配置了flushCache=true属性(参考一级缓存的创建代码截图),
    如果配置了则会清除一级缓存。
  2. MyBatis全局配置属性localCacheScope配置为Statement时,那么完成一次查询就会清除缓存。
  3. 在执行commit,rollback,update方法时会清空一级缓存

二级缓存失效:

  1. 所有的update操作(insert,delete,uptede)都会触发缓存的刷新,从而导致二级缓存失效,所以二级缓存适合在读多写少的场景中开启。
  2. 二级缓存针对的是同一个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元素

图示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语句

  1. item别名
  2. collection传入数据类型
  3. open开始
  4. separator间隔
  5. 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();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/124749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构-考研难点代码突破(C++实现无向图图最小生成树算法(Prim,Kruskal)图解操作细节(引自C语言中文网))

以代码的方式复习考研数据结构知识点&#xff0c;这里在考研不以代码为重点&#xff0c;而是以实现过程为重点 文章目录1. 无向图最小生成树算法Kruskal算法C代码实现Prim算法C代码实现1. 无向图最小生成树算法 常见基本概念记忆&#xff1a; 生成树定义&#xff1a; 无向图中…

MySQL索引相关知识

1、什么是索引&#xff1f; 索引是存储引擎用于提高数据库表的访问速度的一种数据结构。通过给字段​​添加索引​​​可以​​提高数据的读取速度​​​&#xff0c;提高项目的并发能力和抗压能力。​​索引优化​​​时mysql中的一种优化方式。索引的作用相当于​​图书的目录…

一文搞懂Linux内核进程原理及系统调用机制

进程四要素 有一段程序代其执行有进程专用的系统堆栈空间在内核有task_struct数据结构进程有独立的存储空间&#xff0c;拥有专有的用户空间 如果具备前三点缺少第四条&#xff0c;称为“线程”&#xff1b;如果完全没有用户空间&#xff0c;称为“内核线程”;如果共享用户空间…

中国剩余定理

最近总是用到中国剩余定理&#xff0c;以前对于这个定理非常的模糊&#xff0c;有时间静下心来简单的学习一下中国剩余定理&#xff0c;文章没有深度&#xff0c;写下这篇博客以作记录。 中国剩余定理CRT前言一、描述二、中国剩余定理求解方法1.除以三余二2.除以五余三3.除以七…

14. UserAgent 反爬是如何实现的,来看看这篇博客

本篇博客实现 【爬虫训练场】 的第一个反爬案例&#xff0c;User-Agent 反爬。 文章目录什么是 User-Agent 反爬在 Python Flask 中实现 User-Agent 反爬什么是 User-Agent 反爬 User-Agent 反爬是一种防止网站被爬虫爬取的技术。 当爬虫向网站发送 HTTP 请求时&#xff0c;会…

初识Kubernetes:(3)Kubernetes资源管理

初识Kubernetes&#xff1a;&#xff08;3&#xff09;Kubernetes资源管理1 资源管理介绍2 YAML语法介绍2.1 YAML语法介绍2.2 YAML语法示例2.2.1 YAML常量2.2.2 对象2.2.3 数组3 资源管理方式3.1 资源管理方式3.2 命令式对象管理3.2.1 kubectl命令3.2.2 操作&#xff08;comman…

操作系统期末考试必会题库2——进程管理

1、某系统出现故障&#xff0c;通过相关指令查看&#xff0c;CPU占有率为0&#xff0c;内存有大量空余&#xff0c;但是用户在其程序中得不到任何相应&#xff0c;请从进程状态分析&#xff0c;当前用户所使用的进程可能是什么状态&#xff08;就绪&#xff0c;运行&#xff0c…

BLE 蓝牙抓包分析

1. 抓包工具 Ellisys & Ellisys Bluetooth Analyzer ​使用方法&#xff1a;https://blog.csdn.net/weixin_44260005/article/details/121216529​ 2. BLE数据样式 3. 数据分析 3.1 ble蓝牙协议栈 3.2 BLE连接过程 http://doc.iotxx.com/BLE%E6%8A%80%E6%9C%AF%E6%8F%AD%…

如何用Alluxio加速云上深度学习训练?

欢迎来到【微直播间】&#xff0c;2min纵览大咖观点 随着企业数据量的不断增加&#xff0c;为了提高深度学习训练的准确性、加快速度并且降低成本&#xff0c;许多企业开始逐步在云上实施分布式训练的方案&#xff0c;本期内容将结合阿里、微软等实际应用案例&#xff0c;分享…

容器安装mysql

1.自己配置仓库和挂载 仓库内容如下 挂载 2.安装工具包 yum install -y yum-utils 3.从阿里云添加docker仓库 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 我们就能查看到 4.cd回主目录开始一系列安装 yum install d…

软件测评师教程之软件测试基础<一>更新中...

目录一.软件测试分类(1)按照开发阶段划分(2)按照测试实施组织划分(3)按照测试技术划分二.软件测试过程模型(1)V模型(2)W模型(3)H模型(4)X模型(5)前置测试模型(6)测试模型的使用三.软件测试策略(1)测试信息流(2)分析设计阶段1.需求说明书评测2.概要设计说明书评测3.详细设计说明…

手绘图说电子元器件-控制与保护器件

控制与保护器件主要包括继电器、开关、接插件和保险器件等,是电子电路中经常使用的器件。 继电器 继电器是一种常用的控制器件,它可以用较小的电流来控制较大的电流,用低电压来控制高电压,用直流电来控制交流电等,并且可实现控制电路与被控电路之间的完全隔离。 继电…

IPV6探测

目录本机是否支持IPv6如何确认一个网站是否开启 IPv6在线工具&#xff1a;IP查询在线工具&#xff1a;IPv6连接测试在线工具&#xff1a;国家IPv6发展监测平台本地工具局域网设备探测pingMSFThc-Ipv6Ipv6-Toolkit端口探测MSFNmap【存在问题】参考领导提了个问题&#xff0c;怎么…

Mybatis 解析mapper过程

Mapper配置的四种方式 配置方法一共有四种&#xff0c; 分别对应四种解析方式&#xff0c;从解析源码可以看出来 private void mapperElement(XNode parent) throws Exception { //添加接口映射器if (parent ! null) {for (XNode child : parent.getChildren()) { //获取所有…

4.7W防削顶单声道D类音频功率放大器HT6872介绍

HT6872简介 HT6872是一款低EMI&#xff0c;防削顶失真&#xff0c;单声道免滤波D类音频功率放大器。在6.5V电源&#xff0c;10%THDN&#xff0c;4Ω负载条件下&#xff0c;输出4.71W功率&#xff0c;在各类音频终端应用中维持高效率并提供AB类放大器的性能。 HT6872的最大特点是…

C++:设计一个保留字(或关键字)的统计程序,从源数据文件(C或C++语言程序)中,读取字符或字符串,与保留字文件中的保留字进行匹配比较,并统计计数。

2.1题目&#xff1a; 设计一个保留字&#xff08;或关键字&#xff09;的统计程序 l建立保留字文件&#xff1b; l从源数据文件&#xff08;C或C语言程序&#xff09;中&#xff0c;读取字符或字符串&#xff0c;与保留字文件中的保留字进行匹配比较&#xff0c;并统计计数。…

python数据分析(1)numpy基础

iamseancheney/python_for_data_analysis_2nd_chinese_version: 《利用Python进行数据分析第2版》 (github.com) NumPy的ndarray&#xff1a;一种多维数组对象 1.性质 NumPy最重要的一个特点就是其N维数组对象&#xff08;即ndarray&#xff09;&#xff0c;该对象是一个快速…

73.qt quick-通用可拖拽表盘示例

截图如下所示: 效果如下所示: 源码已上传至专栏群(第一章底部获取)中,感兴趣的自行下载 demo使用介绍 控件自定义属性已经封装出来了,如下图所示: main.qml如下所示: import QtQuick 2.14 import QtQuick.Window 2.14 import QtQuick.Extras 1.4 import QtQuick.Layouts 1.1…

微信小程序-会议OA项目03

目录 1.Flex布局简介 1.1 什么是flex布局 1.2 flex属性 2.轮播图--组件的使用 3.会议OA项目-首页 1.Flex布局简介 布局的传统解决方案&#xff0c;基于盒状模型&#xff0c;依赖 display属性 position属性 float属性 1.1 什么是flex布局 1) Flex是Flexible Box的缩写&…

攻防世界-fileclude

题目 访问题目场景 阅读php代码 <?php include("flag.php"); highlight_file(__FILE__); if(isset($_GET["file1"]) && isset($_GET["file2"])) {$file1 $_GET["file1"];$file2 $_GET["file2"];if(!empty($f…