[Java EE 进阶]Mybatis进阶(动态SQL)

一.动态 SQL(XML 版)

1.<if>标签

作用 : 判断参数是否为 null 或满足条件,满足则拼接 SQL ,不满足则跳过

常用属性

test 属性中写的参数名是 Java 属性名,而不是数据库字段

实例 : 动态新增用户

XML 复制代码
<!--    if标签-->
    <insert id="insertUserByCondition">
        insert into user_info (
        username,
        password,
        age,
--      java属性名
        <if test="gender != null">
            gender,
        </if>
        phone)
        values (
        #{username},
        #{age},
        <if test = "gender!=null">
            #{gender},
        </if>
        #{phone});
    </insert>
java 复制代码
//if标签
Integer insertUserByCondition(UserInfo userInfo);

测试代码

java 复制代码
@Test
void insertUserByCondition() {
    UserInfo user = new UserInfo();
    user.setId(5);
    user.setUsername("updateName");
    user.setPassword("updatePwd");
    user.setAge((byte) 20);
    user.setGender((byte) 1);
    user.setPhone("13900139000");
    int tmp = userInfoMapperXML.insertUserByCondition(user);
}

2.<trim>标签

作用 : 统一给 SQL片段加前缀,后缀,或自动去除多余前缀(例如 SQL 中的,逗号和多余的 and)

常用属性 :

  • prefix:整个片段加前缀(如 ( / SET / WHERE
  • suffix:整个片段加后缀(如 )
  • prefixOverrides:要去掉的开头多余字符
  • suffixOverrides:要去掉的末尾多余字符(最常用:,
XML 复制代码
<!--  trim标签  -->
<insert id = "insertUserByTrim">
    insert into user_info
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test =" username != null">
            username,
        </if>
        <if test="password!=null">
            `password`,
        </if>
        <if test="age!=null">
            age,
        </if>
        <if test="gender!=null">
            gender,
        </if>
        <if test="phone!=null">
            phone,
        </if>

    </trim>
    values
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test =" username != null">
            #{username},
        </if>
        <if test="password!=null">
            #{password},
        </if>
        <if test="age!=null">
            #{age},
        </if>
        <if test="gender!=null">
            #{gender},
        </if>
        <if test="phone!=null">
            #{phone},
        </if>
    </trim>
</insert>
java 复制代码
//trim标签
Integer insertUserByTrim(UserInfo userInfo);

测试代码

java 复制代码
@Test
void insertUserByTrim() {
    UserInfo user = new UserInfo();
    user.setId(5);
    user.setUsername("updateName");
    user.setPassword("updatePwd");
    user.setAge((byte) 20);
    user.setGender((byte) 1);
    user.setPhone("13900139000");
    int tmp = userInfoMapperXML.insertUserByCondition(user);
}

以上 sql 动态解析时会做以下处理 :

  1. prefix,加上前缀 : (
  2. suffix,加上后缀 : )
  3. suffixOverrides 会去掉最后一个多余的逗号

3.<where>标签

作用 :

自动生成 where 关键字

删除开头多余的 and/or

没有条件时,不会生成 where,避免语法错误

<where>标签也可以使用<trim prefix = "where" prefixOverrides="and">替换

XML 复制代码
<!--where标签-->
<select id="queryUserByCondition" resultType="com.boop.mybatis.model.UserInfo">
    select id,username,age,gender,phone
    from user_info
    <where>
        <if test="age!=null">
            and age = #{age}
        </if>
        <if test="gender!=null">
            and gender=#{gender}
        </if>
    </where>
</select>

测试代码

java 复制代码
@Test
void queryUserByCondition() {
    UserInfo user = new UserInfo();
    user.setAge((byte)18);
    List<UserInfo> tmp = userInfoMapperXML.queryUserByCondition(user);
}

<where>标签也可以使用<trim prefix = "where" prefixOverrides="and">替换

4.<set>标签

作用 :

自动生成 set 关键字

自动删除末尾多余逗号

等价写法 : <trim prefix="set" suffixOverides = ",">

java 复制代码
//set标签
Integer updateUserByCondition(UserInfo userInfo);
XML 复制代码
<!--  set标签  -->
    <update id="updateUserByCondition">
        update user_info
        <set>
            <if test="username!=null">
                username = #{username},
            </if>
            <if test="age!=null">
                age = #{age},
            </if>
            <if test="deleteFlag!=null">
                delrte_flag = #{deleteFlag};
            </if>
        </set>
        where id = #{id}
    </update>

测试代码

java 复制代码
@Test
void updateUserByCondition() {
    UserInfo us = new UserInfo();
    us.setId(1);//必传参数
    us.setDeleteFlag((byte) 1);
    us.setUsername("lili");
    us.setAge((byte) 266);
    int rows = userInfoMapperXML.updateUserByCondition(us);
    System.out.println("更新行数:"+rows);
}

5.<foreach>标签

主要属性

collection : 集合名称(方法参数名) , 可以是 List , Set , Map 或对象数组

item : 循环中每一项(#{}中要用到的参数名)

open : 语句块开头字符

close : 语句块结尾字符

separator : 每次遍历之间的分隔符

java 复制代码
//foreach标签
void deleteByIds(List<Integer> ids);
XML 复制代码
<!--foreach标签-->
    <delete id="deleteByIds">
        delete from user_info
        where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>

测试代码

java 复制代码
@Test
void deleteByIds() {
    List<Integer> ids = Arrays.asList(17,18,19);
    userInfoMapperXML.deleteByIds(ids);
    System.out.println("批量删除成功,id为"+ids);
}

6.<include>标签

作用 :

把重复的 SQL (如查询字符串,固定条件)抽取成公共片段

多处使用时直接应用 , 便于统一维护

XML 复制代码
<!-- 定义公共SQL片段 -->
<sql id="baseColumn">
    id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>

<!-- 引用片段 -->
<select id="queryAll" resultType="com.boop.mybatis.model.UserInfo">
    SELECT <include refid="baseColumn"/>
    FROM user_info
    WHERE delete_flag = 0
</select>

二.动态 SQL (注解版)

注解版需要使用<script>标签把 SQL 包起来,没有语法提示,容易出错 , 不推荐复杂动态 SQL 使用

java 复制代码
//动态SQL注解版
@Mapper
public interface UserMapper {
    @Insert("<script>" +
            "INSERT INTO user_info (username, age" +
            "<if test='gender != null'>, gender</if>" +
            ") VALUES (#{username}, #{age}" +
            "<if test='gender != null'>, #{gender}</if>" +
            ")</script>")
    Integer insertUser(UserInfo userInfo);
}
相关推荐
小江的记录本5 分钟前
【MySQL】MySQL日志体系:redo log/undo log/binlog 三者区别、两阶段提交、如何保证数据一致性
java·数据库·后端·python·sql·mysql·面试
CC城子15 分钟前
EtherCAT研究之物理层PHY(一)
linux·运维·数据库
摇滚侠16 分钟前
Java 饿汉式 单例模式
java·开发语言·单例模式
yyuuuzz17 分钟前
国际云服务器的技术特点与使用经验
运维·服务器·网络·数据库·云计算·aws
TDengine (老段)19 分钟前
TDengine VNode 生命周期 — 从创建到销毁的完整旅程
大数据·数据库·重构·系统架构·负载均衡·tdengine·涛思数据
2301_7838486520 分钟前
JavaScript中利用Symbol实现单例模式的属性锁定
jvm·数据库·python
Devin~Y21 分钟前
大厂Java面试实录:Spring Boot/WebFlux、JVM调优、Redis/Kafka、Spring Cloud 与 RAG/Agent 追问
java·jvm·spring boot·maven·mybatis·jpa·spring webflux
一轮弯弯的明月22 分钟前
Spring AOP编程
java·开发语言·spring boot·笔记·spring aop·学习心得
Sam_Deep_Thinking24 分钟前
拼单功能的设计实战
java·架构
Boop_wu25 分钟前
[Java项目] Spring Boot + WebSocket 实现网页在线聊天室|完整项目架构与实战讲解
spring boot·websocket·java-ee·mybatis