notebook notebook
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)

学习笔记

啦啦啦,向太阳~
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)
  • Java开发

    • My

    • Posts

    • Java SE

    • Java 并发编程

    • JVM

    • JDBC

    • Java Web

    • Spring 与 SpringMVC

    • Spring Boot

    • Spring Cloud

    • Spring Security

    • Netty

    • MyBatis

      • 动力节点课程-MyBatis

        • MyBatis 概述与入门
        • 使用 MyBatis 完成 CRUD
        • MyBatis 核心配置文件详解
        • MVC 中使用 MyBatis
        • MyBatis 使用小技巧
        • 参数处理、查询返回与动态 SQL
          • 1. Mybatis 参数处理
            • 1.1 单个简单类型参数
            • 1.2 Map 参数
            • 1.3 实体类参数
            • 1.4 多参数
            • 1.5 @Param 注解 —— 命名注解
          • 2. MyBatis 查询语句专题
            • 2.1 返回一个实体类
            • 2.2 返回实体类列表
            • 2.3 返回 Map
            • 2.4 返回 Map<String, Map>
            • 2.5 resultMap 结果映射
          • 3. 动态 SQL
            • 3.1 if 标签
            • 3.2 where 标签
            • 3.3 trim 标签
            • 3.4 set 标签
            • 3.5 choose、when、otherwise
            • 3.6 foreach
            • 3.7 sql 标签和 include 标签
        • MyBatis 的高级映射和缓存机制
  • Python开发

  • Golang开发

  • Git

  • 软件设计与架构

  • 大数据与分布式系统

  • 区块链

  • Nginx

  • 开发
  • Java开发
  • MyBatis
  • 动力节点课程-MyBatis
yubin
2023-08-12
目录

参数处理、查询返回与动态 SQL

# 1. Mybatis 参数处理

这里讲的参数是指的 Mapper 接口中 int insertCar(Car car); 的 car 这样的参数。

# 1.1 单个简单类型参数

简单类型包括:

  • byte short int long float double char
  • Byte Short Integer Long Float Double Character
  • String
  • java.util.Date
  • java.sql.Date

Mapper 接口方法:

List<Student> selectByName(String name);
1

xml 中:

<select id="selectByName" resultType="Student">
  select * from t_student where name = #{name}
</select>
1
2
3

# 1.2 Map 参数

手动封装 Map 集合,将每个条件以 KV 的形式存放到 map 中。然后在使用的时候通过 #{map 中的key} 来取值。

Mapper 接口方法:

List<Student> selectByParamMap(Map<String,Object> paramMap);
1

xml 中:

<select id="selectByParamMap" resultType="Student">
  select * from t_student where name = #{nameKey} and age = #{ageKey}
</select>
1
2
3

# 1.3 实体类参数

#{} 里面写的是属性名字。这个属性名其本质上是:set/get 方法名去掉 set/get 之后的名字。

Mapper 接口方法:

int insert(Student student);
1

xml 中:

<insert id="insert">
  insert into t_student values(null,#{name},#{age},#{height},#{birth},#{sex})
</insert>
1
2
3

# 1.4 多参数

假如有下面这个 Mapper 方法:

List<Student> selectByNameAndSex(String name, Character sex);
1

面对这种多参数的确情况,MyBatis 会自动创建一个 Map 集合,并且 Map 集合是以这样的方式来存储参数的:

map.put("arg0", name);
map.put("arg1", sex);
map.put("param1", name);
map.put("param2", sex);
1
2
3
4

所以 xml 文件可以这样写:

<select id="selectByNameAndSex" resultType="student">
  select * from t_student where name = #{arg0} and sex = #{arg1}
</select>
1
2
3

# 1.5 @Param 注解 —— 命名注解

刚刚 MyBatis 自动创建的 map 的 key 是 arg0、arg1 这样的名字,可读性较差,那我们可以自定义 key 吗?

当然可以!使用 @Param 注解即可。@Param(...) 可以指定 map 集合的 key。

Mapper 接口方法:

List<Student> selectByNameAndAge(@Param("name") String name, @Param("age") int age);
1

xml 文件:

<select id="selectByNameAndAge" resultType="student">
  select * from t_student where name = #{name} and age = #{age}
</select>
1
2
3

# 2. MyBatis 查询语句专题

# 2.1 返回一个实体类

当查询的结果有对应的实体类,并且查询结果只有一条时。

Mapper 方法如下:

Car selectById(Long id);
1

xml 文件:

<select id="selectById" resultType="Car">
    select id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType from t_car where id = #{id}
</select>
1
2
3

# 2.2 返回实体类列表

Mapper 方法:

List<Car> selectAll();
1

xml 文件:

<select id="selectAll" resultType="Car">
  select id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType from t_car
</select>
1
2
3

# 2.3 返回 Map

当返回的数据,没有合适的实体类对应的话,可以采用 Map 集合接收。字段名做 key,字段值做 value。

查询如果可以保证只有一条数据,则返回一个 Map 集合即可。

Map<String, Object> selectById(Long id);
1
<select id="selectById" resultType="map">
  select id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType from t_car where id = #{id}
</select>
1
2
3

写 resultMap="map",这是因为 MyBatis 内置了很多别名。【参见mybatis开发手册】

当然,如果返回多个记录,可以使用 List<Map> 来接收。

# 2.4 返回 Map<String, Map>

比如我们想 selectAll() 的返回结果是一个 map,其中 key 为 car id,value 是 car 对象信息,那么我们可以用 Map<String, Map> 来接收,内层的 map 代表一个 car 对象的信息。

@MapKey("id")
Map<Long,Map<String,Object>> selectAll();
1
2
<select id="selectAllRetMap" resultType="map">
  select id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType from t_car
</select>
1
2
3

# 2.5 resultMap 结果映射

查询结果的列名和 Java 对象的属性名对应不上怎么办(比如 car_type 与 carType)?解决方法有三种:

  1. 方法 1:使用 AS 关键字给 column 起别名
  2. 方法 2:使用 resultMap 进行结果映射
  3. 方法 3:开启驼峰命名自动映射(配置 settings)

# 2.5.1 使用 resultMap 进行结果映射

List<Car> selectAll();
1
<!--
        resultMap:
            id:这个结果映射的标识,作为select标签的resultMap属性的值。
            type:结果集要映射的类。可以使用别名。
-->
<resultMap id="carResultMap" type="Car">
  <!--对象的唯一标识,官方解释是:为了提高mybatis的性能。建议写上。-->
  <id property="id" column="id"/>
  <result property="carNum" column="car_num"/>
  <!--当属性名和数据库列名一致时,可以省略。但建议都写上。-->
  <!--javaType用来指定属性类型。jdbcType用来指定列类型。一般可以省略。-->
  <result property="brand" column="brand" javaType="string" jdbcType="VARCHAR"/>
  <result property="guidePrice" column="guide_price"/>
  <result property="produceTime" column="produce_time"/>
  <result property="carType" column="car_type"/>
</resultMap>

<!--resultMap属性的值必须和resultMap标签中id属性值一致。-->
<select id="selectAll" resultMap="carResultMap">
  select * from t_car
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 2.5.2 开启驼峰命名自动映射

使用这种方式的前提是:属性名遵循 Java 的命名规范,数据库表的列名遵循 SQL 的命名规范。

  • Java 命名规范:首字母小写,后面每个单词首字母大写,遵循驼峰命名方式。
  • SQL 命名规范:全部小写,单词之间采用下划线分割。

启用该配置的方式是在 mybatis-config.xml 文件中:

<!--放在properties标签后面-->
<settings>
  <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
1
2
3
4

# 2.5.3 返回总记录条数

Mapper 接口:

Long selectTotal();
1

xml 文件:

<!--long是别名,可参考mybatis开发手册。-->
<select id="selectTotal" resultType="long">
  select count(*) from t_car
</select>
1
2
3
4
  • 这里 resultType 的 long 也是别名

# 3. 动态 SQL

动态 SQL 的场景:多条件查询等。

20230813154001

# 3.1 if 标签

需求:多条件查询

Mapper 接口:

List<Car> selectByMultiCondition(@Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("carType") String carType);
1

xml 文件:

<select id="selectByMultiCondition" resultType="car">
  select * from t_car where
  <if test="brand != null and brand != ''">
    brand like #{brand}"%"
  </if>
  <if test="guidePrice != null and guidePrice != ''">
    and guide_price >= #{guidePrice}
  </if>
  <if test="carType != null and carType != ''">
    and car_type = #{carType}
  </if>
</select>
1
2
3
4
5
6
7
8
9
10
11
12

但如果第一个条件为空,其余两个不为空,那么拼接生成的 SQL 多出一个 and,解决办法就是下面要说的 where 标签。

# 3.2 where 标签

where 标签的作用:让 WHERE 子句更加动态智能。

  • 当所有条件为空时,where 标签保证不会生成 WHERE 子句。
  • 自动去除某些条件前面多余的 AND 或者 OR。

使用 where 标签后,上面的 xml 示例可以改成:

<select id="selectByMultiCondition" resultType="car">
  select * from t_car
  <where>
    <if test="brand != null and brand != ''">
      brand like #{brand}"%"
    </if>
    <if test="guidePrice != null and guidePrice != ''">
      and guide_price >= #{guidePrice}
    </if>
    <if test="carType != null and carType != ''">
      and car_type = #{carType}
    </if>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13

如果你的写法是每个 if 标签里把 and 或 or 写在后面,那 where 标签无法自动去掉最后多余的 and/or

# 3.3 trim 标签

trim 标签的属性:

  • prefix:在 trim 标签中的语句前添加内容
  • suffix:在 trim 标签中的语句后添加内容
  • prefixOverrides:前缀覆盖掉(去掉)
  • suffixOverrides:后缀覆盖掉(去掉)

Mapper 接口:

List<Car> selectByMultiConditionWithTrim(@Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("carType");
1

xml 文件:

<select id="selectByMultiConditionWithTrim" resultType="car">
  select * from t_car
  <trim prefix="where" suffixOverrides="and|or">
    <if test="brand != null and brand != ''">
      brand like #{brand}"%" and
    </if>
    <if test="guidePrice != null and guidePrice != ''">
      guide_price >= #{guidePrice} and
    </if>
    <if test="carType != null and carType != ''">
      car_type = #{carType}
    </if>
  </trim>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3.4 set 标签

主要用在 UPDATE 语句中,用来生成 set 关键字,同时去掉最后多余的逗号。

比如我们只更新提交的不为空的字段,如果提交的数据是空或者"",那么这个字段我们将不更新。

Mapper 接口:

int updateWithSet(Car car);
1

xml 文件:

<update id="updateWithSet">
  update t_car
  <set>
    <if test="carNum != null and carNum != ''">car_num = #{carNum},</if>
    <if test="brand != null and brand != ''">brand = #{brand},</if>
    <if test="guidePrice != null and guidePrice != ''">guide_price = #{guidePrice},</if>
    <if test="produceTime != null and produceTime != ''">produce_time = #{produceTime},</if>
    <if test="carType != null and carType != ''">car_type = #{carType},</if>
  </set>
  where id = #{id}
</update>
1
2
3
4
5
6
7
8
9
10
11

# 3.5 choose、when、otherwise

这三个标签是一起使用的,格式为:

<choose>
  <when></when>
  <when></when>
  <when></when>
  <otherwise></otherwise>
</choose>
1
2
3
4
5
6

这等同于:

if () {
    ...
} else if () {
    ...
} else if () {
    ...
} else if () {
    ...
} else {
    ...
}
1
2
3
4
5
6
7
8
9
10
11

只有一个分支会被选择。

需求:先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据生产日期查询。

List<Car> selectWithChoose(@Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("produceTime") String produceTime);
1

xml 文件:

<select id="selectWithChoose" resultType="car">
  select * from t_car
  <where>
    <choose>
      <when test="brand != null and brand != ''">
        brand like #{brand}"%"
      </when>
      <when test="guidePrice != null and guidePrice != ''">
        guide_price >= #{guidePrice}
      </when>
      <otherwise>
        produce_time >= #{produceTime}
      </otherwise>
    </choose>
  </where>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 3.6 foreach

循环数组或集合,动态生成 SQL,比如这样的 SQL:

delete from t_car where id in(1,2,3);
delete from t_car where id = 1 or id = 2 or id = 3;
1
2

下面以批量删除为例来展示用来,当然批量插入也可以用这个标签。

int deleteBatchByForeach(@Param("ids") Long[] ids);
1
<delete id="deleteBatchByForeach">
  delete from t_car where id in
  <foreach collection="ids" item="id" separator="," open="(" close=")">
    #{id}
  </foreach>
</delete>
1
2
3
4
5
6

foreach 的属性:

  • collection:集合或数组
  • item:集合或数组中的元素
  • separator:分隔符
  • open:foreach 标签中所有内容的开始
  • close:foreach 标签中所有内容的结束

# 3.7 sql 标签和 include 标签

  • sql 标签用来声明 SQL 片段
  • include 标签用来将声明的 SQL 片段包含到某个 SQL 语句当中

作用:代码复用

<sql id="carCols">id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType</sql>

<select id="selectAllRetMap" resultType="map">
  select <include refid="carCols"/> from t_car
</select>

<select id="selectAllRetListMap" resultType="map">
  select <include refid="carCols"/> carType from t_car
</select>

<select id="selectByIdRetMap" resultType="map">
  select <include refid="carCols"/> from t_car where id = #{id}
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
编辑 (opens new window)
上次更新: 2023/08/24, 10:58:33
MyBatis 使用小技巧
MyBatis 的高级映射和缓存机制

← MyBatis 使用小技巧 MyBatis 的高级映射和缓存机制→

最近更新
01
Deep Reinforcement Learning
10-03
02
误删数据后怎么办
04-06
03
MySQL 一主多从
03-22
更多文章>
Theme by Vdoing | Copyright © 2021-2024 yubincloud | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×