Springboot Mybatis 动态SQL

动态SQL

XML 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wzb.SqlImprove20240925.SQLImproveMapper">

    <!-- 将条件查询改成动态SQL形式 -->
    <!-- XML中,是对SQL语句进行拼接的,将若干SQL语句的条件,拼接成一条完整的SQL语句 -->
    <!-- <if>标签用于判断条件是否成立,用test属性进行条件判断,若条件为true,那么就拼接SQL,若为false,则不操作 -->
    <!--    <select id="sqlImprove" resultType="com.wzb.Pojo20240925.Emp">-->
    <!--        select * from emp-->
    <!--        where-->
    <!--        <if test="name != null">-->
    <!--            name like concat('%', #{name}, '%')-->
    <!--        </if>-->

    <!--        <if test="gender != -1">-->
    <!--            and gender = #{gender}-->
    <!--        </if>-->

    <!--        <if test="begin != null and end != null">-->
    <!--            and entrydate between #{begin} and #{end}-->
    <!--        </if>-->
    <!--        order by update_time desc-->
    <!--    </select>-->

    <!-- 上述代码看似完成了条件查询,但其实仍然有不足之处:
    1.若所有参数都是null,那么仍然会在SQL语句中拼接where,这是不符合SQL语法的
    2.若前面的是null,但是后面的参数不是null,那么会多拼接一个null,比如上面的代码:name是null;但是gender不是null
      那么就会拼接成"...... where and gender = #{gender}",这是错误的SQL语句
    -->

    <!-- 解决方法:<where>标签:
         <where>标签只会在子元素(参数)有内容的情况下,才会插入where子句,并且能够自动去除子句开头的and或者or -->


    <!-- 优化代码 -->
    <!-- 当参数没有传递(为null时),就不会将语句拼接成SQL语句,并且用了<where>标签,能够自动处理开头的and、or -->
    <select id="sqlImprove" resultType="com.wzb.Pojo20240925.Emp">
        select * from emp
        <where>
            <if test="name != null">
                and name like concat('%', #{name}, '%')
            </if>

            <if test="gender != -1">
                and gender = #{gender}
            </if>

            <if test="begin != null and end != null">
                and entrydate between begin and end
            </if>
        </where>
        order by update_time desc
    </select>
    <!-- 测试成功,成功实现动态SQL -->


    <!-- 实现动态更新员工信息 -->
<!--    <update id="updateImprove">-->
<!--        update emp-->
<!--        set-->
<!--        <if test="username != null">-->
<!--            username=#{username},-->
<!--        </if>-->
<!--        <if test="name != null">-->
<!--            name=#{name},-->
<!--        </if>-->
<!--        <if test="gender != -1">-->
<!--            gender=#{gender},-->
<!--        </if>-->
<!--        <if test="image != null">-->
<!--            image=#{image},-->
<!--        </if>-->
<!--        <if test="job != null">-->
<!--            job=#{job},-->
<!--        </if>-->
<!--        <if test="entrydate != null">-->
<!--            entrydate=#{entrydate},-->
<!--        </if>-->
<!--        <if test="deptId != null">-->
<!--            dept_id=#{deptId},-->
<!--        </if>-->
<!--        <if test="updateTime != null">-->
<!--            update_time=#{updateTime}-->
<!--        </if>-->
<!--        where id = #{id}-->
<!--    </update>-->

    <!-- 这个代码会出现问题,若只传递前面的参数,不传递最后一个参数,那么将会多出一个","(因为每一个拼接语句的末尾都有个逗号,
    只有最后一1个拼接语句没有),所以说只要不传递最后一个参数,就会发生SQL语句语法错误 -->

    <!-- 解决方法:使用标签<set>
         在update语句中使用<set>标签,会删除掉额外的逗号,避免SQL语法错误 -->

    <update id="updateImprove">
        update emp
        <set>
            <if test="username != null">
                username=#{username},
            </if>
            <if test="name != null">
                name=#{name},
            </if>
            <if test="gender != -1">
                gender=#{gender},
            </if>
            <if test="image != null">
                image=#{image},
            </if>
            <if test="job != null">
                job=#{job},
            </if>
            <if test="entrydate != null">
                entrydate=#{entrydate},
            </if>
            <if test="deptId != null">
                dept_id=#{deptId},
            </if>
            <if test="updateTime != null">
                update_time=#{updateTime}
            </if>
        </set>
        where id = #{id}
    </update>

    <!-- 这样可以解决update语句后多","的问题 -->

    <!-- 小结:
         <if>标签可以用于判断条件是否成立,若条件为true,那么拼接对应的SQL语句
         <where>标签代替where,只会在子元素不为null的时候才插入where子句,并且能够自动去除子句开头的多余的and和or
         <set>标签代替set在update语句中使用,可以动态的插入update子句,并且能删除额外的"," -->

    <!-- 使用<foreach>标签达到删除多条语句的效果 -->
    <!-- <foreach collection="集合名称" item="集合遍历出来的元素", separator="每一次遍历使用的分隔符"
          open="遍历开始之前拼接的片段" close="遍历结束后拼接的片段"> -->
    <delete id="deleteImprove">
        delete from emp where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>
    <!-- 成功使用<foreach>完成批量删除 -->

    <!-- 在XML映射文件中配置SQL,有时会出现很多重复的片段,那么就会导致很多冗余的代码 -->

</mapper>

SQLImproveMapper

java 复制代码
package com.wzb;

import com.wzb.MybatisExercise20240925.EmpMapper;
import com.wzb.MybatisXmlExercise20240925.XmlMapper;
import com.wzb.Pojo20240925.Emp;
import com.wzb.SqlImprove20240925.SQLImproveMapper;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@SpringBootTest
class SpringbootExercise20240925ApplicationTests {

    @Autowired
    private EmpMapper empMapper;

    @Autowired
    private XmlMapper xmlMapper;

    @Autowired
    private SQLImproveMapper sqlImproveMapper;

    // 增
//    @Test
//    public void insertEmp() {
//        Emp emp = new Emp();
//        emp.setUsername("black");
//        emp.setName("布莱克");
//        emp.setGender((short)1);
//        emp.setImage("2.jpg");
//        emp.setJob((short)2);
//        emp.setEntrydate(LocalDate.of(2000, 1, 1));
//        emp.setCreateTime(LocalDateTime.now());
//        emp.setUpdateTime(LocalDateTime.now());
//
//        empMapper.insertEmp(emp);
//    }

//    // 删
//    @Test
//    public void deleteEmp() {
//        empMapper.deleteEmp(20);
//    }
//
//    // 改
//    @Test
//    public void updateEmp() {
//        Emp emp = new Emp();
//        emp.setId(19);
//        emp.setUsername("gaiya");
//        emp.setName("盖亚");
//        emp.setGender((short)1);
//        emp.setImage("2.jpg");
//        emp.setJob((short)2);
//        emp.setEntrydate(LocalDate.of(2000, 1, 1));
//        emp.setCreateTime(LocalDateTime.now());
//        emp.setUpdateTime(LocalDateTime.now());
//
//        empMapper.updateEmp(emp);
//    }
//
//    // 查
//    @Test
//    public void selectEmp() {
//        Emp emp = empMapper.selectEmp(19);
//        System.out.println(emp);
//    }

    @Test
    public void XmlConditionSelect() {
        List<Emp> empList = xmlMapper.conditionSelect("张", (short) 1, null, null
                /*LocalDate.of(2000, 1, 1), LocalDate.of(2024,1,1)*/);
        for (Emp emp : empList) {
            System.out.println(emp);
        }

    }

    @Test
    public void SqlImprove() {
        List<Emp> empList = sqlImproveMapper.sqlImprove(null, (short) -1, null, null);
        for (Emp emp : empList) {
            System.out.println(emp);
        }
    }

    @Test
    public void updateEmp() {
        Emp emp = new Emp();
        emp.setUsername("tom2");
        sqlImproveMapper.updateImprove(emp);
    }

    @Test
    public void deleteEmp() {
        List<Integer> ids = new ArrayList<>();
        Collections.addAll(ids, 18,19,26,27);
        sqlImproveMapper.deleteImprove(ids);
    }
}
相关推荐
lang201509284 小时前
MyBatis配置全解析:核心要点详解
mybatis
用户281113022214 小时前
分布式事务总结
后端
小帅说java4 小时前
【Spring开发】SpringCloud服务端基础框架第9篇:3.Gateway服务网关【附代码文档】
javascript·spring
xuejianxinokok4 小时前
新版本 python 3.14 性能到底如何?
后端·python
Ray664 小时前
代理模式
后端
考虑考虑4 小时前
Jpa中的枚举类型
spring boot·后端·spring
peter5274 小时前
LangChain4j入门使用
后端
ArabySide4 小时前
【ASP.NET Core】分布式场景下ASP.NET Core中JWT应用教程
分布式·后端·asp.net core
hui函数5 小时前
Python全栈(基础篇)——Day06:后端内容(定义函数+调用函数+实战演示+每日一题)
后端·python
用户874034852515 小时前
家政小程序源码实战:快速部署+多端适配,打造高效家政服务生态
spring boot