[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);
}
相关推荐
Elastic 中国社区官方博客2 小时前
使用 EDOT Browser 和 Kibana 进行 OpenTelemetry 浏览器端埋点
大数据·服务器·数据库·elasticsearch·搜索引擎·单元测试·可用性测试
星轨zb2 小时前
为什么Mysql需要索引以及如何应用到项目中
数据库·mysql
BullSmall2 小时前
Redis 双机部署 完整方案(两种架构,适配两台机器)
java·redis·架构
Old Uncle Tom3 小时前
提示词编写规范
数据库·算法
l1t3 小时前
DeepSeek总结的Postgres 扩展天花板:当一个实例试图包揽一切时
数据库·postgresql
我要升天!3 小时前
C语言连接 MySQL:libmysqlclient 获取方式详解
c语言·开发语言·数据库·mysql·adb
A-Jie-Y3 小时前
JAVA23种设计模式
java·设计模式
小同志003 小时前
IoC 详解
java·开发语言