Mybatis动态SQL

文章介绍了Mybatis中动态SQL的使用,包括if标签解决的SQL条件拼接问题,where标签避免多余的AND以及优化SQL语法,以及foreach标签在批量操作中的应用。通过示例展示了如何避免空值导致的SQL错误并提高代码的灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

# Mybatis动态SQL

一、if标签

image-20230508162539150

这个SQL语句固定死了,假如我们只输入张,后面几个都是空,是查不出结果的,所以是有问题的,我们希望在任意一个输入框输出内容,其他的输入框不输入,就都能查出来。

empMapper.xml

image-20230508165454613
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
    <!-- id于mapper接口中的方法名一致
    resultType是单条记录封装的类型-->
    <select id="select" resultType="com.itheima.pojo.Emp">
        select *
        from emp
        where
        <if test="name != null">
            name like concat('%', #{name}, '%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="begin != null and end != null">
            and entrydate between #{begin} and #{end}
        </if>
        order by update_time desc
    </select>
</mapper>

测试

1、

//        动态SQL
        List<Emp> empList = empMapper.select("张", null, null, null);
        System.out.println(empList);

2、

List<Emp> empList = empMapper.select(null, (short)1, null, null);
System.out.println(empList);

报错

Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'and gender = 1

image-20230508165817247

找到and gender,因为

image-20230508165902650

因为name为null,所以直接执行第二个if,不为空,就带上了and,sql语法错误。

mybatis提供了where标签

--          where标签作用:1、判断所有标签是否成立,不成立就不生成where
--                       2、去掉标签中的and
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
    <!-- id于mapper接口中的方法名一致
    resultType是单条记录封装的类型-->
    <select id="select" resultType="com.itheima.pojo.Emp">
        select *
        from emp
--          where标签作用:1、判断所有标签是否成立,不成立就不生成where
--                       2、去掉标签中的and
        <where>
        <if test="name != null">
            name like concat('%', #{name}, '%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="begin != null and end != null">
            and entrydate between #{begin} and #{end}
        </if>
        order by update_time desc
        </where>
    </select>
</mapper>
image-20230508170443595 image-20230508170615926

二、if案例

image-20230508194818879
//固定写死的更新
@Update("update emp set username=#{username},name=#{name},gender=#{gender},image=#{image},job=#{job},entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime}" +
        " where id=#{id}")
public void update(Emp emp);
image-20230508171738837

没有image,job,entrdate,这样更新之后,这些字段为null

image-20230508194530870

当我们使用了动态SQL

首先在empMapper接口中新添加一个方法update2

public void update2(Emp emp);

其次在EmpMapper.xml中添加

<update id="update2">
    update emp
    <set>
        <if test="username!=null">
            username=#{username},
        </if>
        <if test="name!=null">
            name=#{name},
        </if>
        <if test="gender!=null">
            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>

最后进行测试

//动态更新
@Test
public void update2(){
    // 创建Emp对象
    Emp emp = new Emp();
    emp.setId(21);
    emp.setUsername("Tom555");
    emp.setName("汤姆555");
    emp.setGender((short)2);
    emp.setUpdateTime(LocalDateTime.now());
    empMapper.update2(emp);
}
image-20230508195237131

可以看到其余的信息都在。

image-20230508194903073

小结

image-20230508195556853

三、foreach标签

批量删除,首先先写SQL语句

image-20230508202225886

其次,在EmpMapper接口中声明一个方法

//    批量删除
    public void deleteByIds(List<Integer> ids);

在EmpMapper.xml中书写SQL语句

<!--    批量删除(18,19,20)-->
<!--    collection:集合名称
        item:遍历出来的元素/项
        separator:分隔符是什么
        open:遍历开始前拼接的片段
        close:遍历结束后拼接的片段
-->
<delete id="deleteByIds">
    delete from emp where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>
image-20230508205608015

最后测试

//    删除多条员工信息
    @Test
    public void deleteByIds(){
        List<Integer> list = Arrays.asList(16,21);
        empMapper.deleteByIds(list);
    }

结果:image-20230508205648473

image-20230508205716425

四、sql&include标签

代码复用性比较差,因为有许多重复的,在后期维护的时候需要都修改,在Java中是用封装的办法提高代码的复用性

image-20230508211811355 image-20230508211739222

将这段代码抽取

image-20230508212157221

引用

image-20230508212327288

小结

image-20230508212534242

一、if标签

image-20230508162539150

这个SQL语句固定死了,假如我们只输入张,后面几个都是空,是查不出结果的,所以是有问题的,我们希望在任意一个输入框输出内容,其他的输入框不输入,就都能查出来。

empMapper.xml

image-20230508165454613
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
    <!-- id于mapper接口中的方法名一致
    resultType是单条记录封装的类型-->
    <select id="select" resultType="com.itheima.pojo.Emp">
        select *
        from emp
        where
        <if test="name != null">
            name like concat('%', #{name}, '%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="begin != null and end != null">
            and entrydate between #{begin} and #{end}
        </if>
        order by update_time desc
    </select>
</mapper>

测试

1、

//        动态SQL
        List<Emp> empList = empMapper.select("张", null, null, null);
        System.out.println(empList);

2、

List<Emp> empList = empMapper.select(null, (short)1, null, null);
System.out.println(empList);

报错

Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'and gender = 1

image-20230508165817247

找到and gender,因为

image-20230508165902650

因为name为null,所以直接执行第二个if,不为空,就带上了and,sql语法错误。

mybatis提供了where标签

--          where标签作用:1、判断所有标签是否成立,不成立就不生成where
--                       2、去掉标签中的and
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
    <!-- id于mapper接口中的方法名一致
    resultType是单条记录封装的类型-->
    <select id="select" resultType="com.itheima.pojo.Emp">
        select *
        from emp
--          where标签作用:1、判断所有标签是否成立,不成立就不生成where
--                       2、去掉标签中的and
        <where>
        <if test="name != null">
            name like concat('%', #{name}, '%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="begin != null and end != null">
            and entrydate between #{begin} and #{end}
        </if>
        order by update_time desc
        </where>
    </select>
</mapper>
image-20230508170443595 image-20230508170615926

二、if案例

image-20230508194818879
//固定写死的更新
@Update("update emp set username=#{username},name=#{name},gender=#{gender},image=#{image},job=#{job},entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime}" +
        " where id=#{id}")
public void update(Emp emp);
image-20230508171738837

没有image,job,entrdate,这样更新之后,这些字段为null

image-20230508194530870

当我们使用了动态SQL

首先在empMapper接口中新添加一个方法update2

public void update2(Emp emp);

其次在EmpMapper.xml中添加

<update id="update2">
    update emp
    <set>
        <if test="username!=null">
            username=#{username},
        </if>
        <if test="name!=null">
            name=#{name},
        </if>
        <if test="gender!=null">
            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>

最后进行测试

//动态更新
@Test
public void update2(){
    // 创建Emp对象
    Emp emp = new Emp();
    emp.setId(21);
    emp.setUsername("Tom555");
    emp.setName("汤姆555");
    emp.setGender((short)2);
    emp.setUpdateTime(LocalDateTime.now());
    empMapper.update2(emp);
}
image-20230508195237131

可以看到其余的信息都在。

image-20230508194903073

小结

image-20230508195556853

三、foreach标签

批量删除,首先先写SQL语句

image-20230508202225886

其次,在EmpMapper接口中声明一个方法

//    批量删除
    public void deleteByIds(List<Integer> ids);

在EmpMapper.xml中书写SQL语句

<!--    批量删除(18,19,20)-->
<!--    collection:集合名称
        item:遍历出来的元素/项
        separator:分隔符是什么
        open:遍历开始前拼接的片段
        close:遍历结束后拼接的片段
-->
<delete id="deleteByIds">
    delete from emp where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>
image-20230508205608015

最后测试

//    删除多条员工信息
    @Test
    public void deleteByIds(){
        List<Integer> list = Arrays.asList(16,21);
        empMapper.deleteByIds(list);
    }

结果:image-20230508205648473

image-20230508205716425

四、sql&include标签

代码复用性比较差,因为有许多重复的,在后期维护的时候需要都修改,在Java中是用封装的办法提高代码的复用性

image-20230508211811355 image-20230508211739222

将这段代码抽取

image-20230508212157221

引用

image-20230508212327288

小结

image-20230508212534242
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值