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);
    }
}
相关推荐
晚风_END6 分钟前
postgresql数据库|连接池中间件pgbouncer的部署和配置详解
数据库·后端·spring·postgresql·中间件·个人开发
梵得儿SHI13 分钟前
(第九篇)Spring AI 核心技术攻坚:安全防护 企业级 AI 应用的风控体系之全链路防护(API 安全到内容合规)
java·人工智能·安全·spring·安全防护·springai·企业级ai
岁岁种桃花儿19 分钟前
构建SpringBoot项目Docker镜像并发布到k8s集群中进行运行
spring boot·docker·kubernetes
九转苍翎23 分钟前
掌控消息全链路(3)——RabbitMQ/Spring-AMQP高级特性详解之TTL、死信和延迟
spring boot·java-rabbitmq
Blossom.11825 分钟前
把大模型当“编译器”用:一句自然语言直接生成SoC的Verilog
数据库·人工智能·python·sql·单片机·嵌入式硬件·fpga开发
九皇叔叔26 分钟前
【07】SpringBoot3 MybatisPlus 删除(Mapper)
java·开发语言·mybatis·mybatis plus
sheji341627 分钟前
【开题答辩全过程】以 基于Spring Boot的化妆品销售系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
只是懒得想了27 分钟前
Go服务限流实战:基于golang.org/x/time/rate与uber-go/ratelimit的深度解析
开发语言·后端·golang
VX:Fegn08959 小时前
计算机毕业设计|基于ssm + vue超市管理系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·后端·课程设计
麦聪聊数据9 小时前
智慧医疗数据互联互通:使用 QuickAPI 构建实时诊疗数据交换层
数据库·sql·安全