【MyBatis】动态SQL

发布于:2025-03-06 ⋅ 阅读:(289) ⋅ 点赞:(0)

目录

一、什么是动态SQL查询

二、动态SQL的使用

2.1 if标签

2.2 trim标签

2.3 where标签

2.4 set标签

2.5 foreach标签


一、什么是动态SQL

MyBatis 是一个流行的持久层框架,用于在 Java 应用程序中与数据库进行交互。动态 SQL 是 MyBatis 提供的一种强大功能,它允许开发者在 SQL 查询中根据条件动态地生成不同的 SQL 语句。这种功能使得 SQL 更加灵活和可维护,尤其是在需要根据多种条件来构建查询的情况下。

动态 SQL 查询的核心在于可以根据不同的输入参数或者条件,动态地调整 SQL 语句的结构。例如,可以根据某些参数决定是否包含某个 SQL 片段,生成 WHERE 子句,或者选择性地加入不同的字段等。

如当你注册个人信息时,有些选项是必填如你的姓名、电话号码等,而有些选项是选填如你的爱好、喜欢的颜色等。这个时候就需要你填入的信息是一个空即' ',而不是一个 null ,这个时候就会使用到动态 SQL 。

创建一个数据表 userinfo 以这个表来进行演示,其中 photo 字段为,当没有显式指定一个字段时将默认赋值为一个空值,如下代码所示:

mysql> create table userinfo(
    -> id int primary key auto_increment,
    -> username varchar(100) not null,
    -> password varchar(30) not null,
    -> photo varchar(500) default '');
Query OK, 0 rows affected (0.02 sec)

mysql> insert into userinfo(id,username,password,photo) values
    -> (1,"zhangsan","123","cat.png"),
    -> (2,"lisi","456","");
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from userinfo;
+----+----------+----------+---------+
| id | username | password | photo   |
+----+----------+----------+---------+
|  1 | zhangsan | 123      | cat.png |
|  2 | lisi     | 456      |         |
+----+----------+----------+---------+
2 rows in set (0.00 sec)

此外 MyBatis 项目里应有:

实体类 UserInfo

@Data
public class UserInfo {
    private int id;
    private String username;
    private String password;
    private String photo;
}

接口 UserMapper 

@Mapper
public interface UserMapper {
}

以及 UserMapper.xml 

<?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.example.demo.dao.UserMapper">
</mapper>

二、动态SQL的使用

2.1 if标签

<if></if>标签:用于满足指定条件时包含的某段 sql 语句。

UserMapper 接口: 

@Mapper
public interface UserMapper {
    int insert(UserInfo userInfo);
}

UserMapper.xml :

<?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.example.demo.dao.UserMapper">

        <insert id="insert">
                insert into userinfo(id,username,password
                <if test="photo!=null">
                        ,photo
                </if>
                )values(#{id},#{username},#{password}
                <if test="photo!=null">
                        ,#{photo}
                </if>
                )
        </insert>

</mapper>

上述代码中 <if> 标签的 test 是满足某个条件时则执行 <if> 标签内的内容,如不满足则不执行,因此当我们需要某个字段添加时某个字段不添加时则会用到 <if> 标签,如下场景:

@SpringBootTest
class UserMapperTest {
    @Autowired
    private UserMapper userMapper;
    @Test
    void testInsert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(3);
        userInfo.setUsername("Bob");
        userInfo.setPassword("787");
        userInfo.setPhoto("dog.png");
        int ret = userMapper.insert(userInfo);
        System.out.println("执行了:"+ret+"条操作");
    }
}

结果为:

 

当某条属性未添加时,新添记录中那条属性则为空:

    @Test
    void testInsert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(4);
        userInfo.setUsername("Ali");
        userInfo.setPassword("777");
        int ret = userMapper.insert(userInfo);
        System.out.println("执行了:"+ret+"条操作");
    }

结果为: 


2.2 trim标签

<trim></trim>标签:当某些选项是非必选时,则可以用到 <trim> 标签和 <if></if> 标签的结合体来完成操作。

  • prefix:表示整个语句块,以prefix的值作为前缀
  • suffix:表示整个语句块,以suffix的值作为后缀
  • prefixOverrides:表示整个语句块要去除掉的前缀
  • suffixOverrides:表示整个语句块要去除掉的后缀

 UserMapper 接口:

    int insert2(UserInfo userInfo);

UserMapper.xml: 

        <insert id="insert2">
                insert into userinfo
                <trim prefix="(" suffix=")" suffixOverrides=",">
                        <if test="username!=null">
                                username,
                        </if>
                        <if test="password!=null">
                                password,
                        </if>
                        <if test="photo!=null">
                                photo,
                        </if>
                </trim>
                values
                <trim prefix="(" suffix=")" suffixOverrides=",">
                        <if test="username!=null">
                                #{username},
                        </if>
                        <if test="password!=null">
                                #{password},
                        </if>
                        <if test="photo!=null">
                                #{photo},
                        </if>
                </trim>
        </insert>

 测试:

    @Test
    void insert2() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("laoliu");
        userInfo.setPassword("666");
        int ret = userMapper.insert2(userInfo);
        System.out.println("执行了:"+ret+"条操作");
    }

结果为: 

 

通过上述代码我们可以了解到 xml 文件中的 <trim prefix="(" suffix=")" suffixOverrides=","> 代表着开头为(、结尾为)、整个语句块要去除掉的后缀为,。


2.3 where标签

<where>标签:会自动添加“where”关键字,并在必要时省去前置的“and”或“or”。

UserMapper接口:

    List<UserInfo> selectAllByWhere(UserInfo userInfo);

UserMapper.xml: 

        <select id="selectAllByWhere" resultType="com.example.demo.model.UserInfo">
                select * from userinfo
                <where>
                        <if test="id>0">
                                and #{id}
                        </if>
                        <if test="username!=null">
                                and username=#{username}
                        </if>
                        <if test="password!=null">
                                and password=#{password}
                        </if>
                        <if test="photo!=null">
                                and photo=#{photo}
                        </if>
                </where>
        </select>
    @Test
    void selectAllByWhere() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("zhangsan");
        userInfo.setPassword("123");
        List<UserInfo> list = userMapper.selectAllByWhere(userInfo);
        System.out.println(list);
    }

通过上述代码,我们可以了解到非必传条件可用到 where,而且 where 如果有满足条件的语句的话会默认去除最前面的 and 或 or。

结果为:

 <trim>标签与<if>标签的结合也可替换上述的<where>标签:

                <trim prefix="where" prefixOverrides="and">
                        <if test="id>0">
                                and #{id}
                        </if>
                        <if test="username!=null">
                                and username=#{username}
                        </if>
                        <if test="password!=null">
                                and password=#{password}
                        </if>
                        <if test="photo!=null">
                                and photo=#{photo}
                        </if>
                </trim>

2.4 set标签

<set>标签:用于“update”语句,自动添加“set”关键字并省去多余的逗号

UserMapper接口:

    int upDateById(UserInfo userInfo);

UserMapper.xml: 

        <update id="upDateById">
                update userinfo
                <set>
                        <if test="username!=null">
                               username=#{username},
                        </if>
                        <if test="password!=null">
                                password=#{password},
                        </if>
                        <if test="photo!=null">
                                photo=#{photo}
                        </if>
                </set>
                where id=#{id}
        </update>

 测试:

    @Test
    void upDateById() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(5);
        userInfo.setUsername("laoba");
        userInfo.setPassword("868");
        int ret = userMapper.upDateById(userInfo);
        System.out.println("执行了:"+ret+"条语句");
    }

结果为: 


2.5 foreach标签

<foreach>标签:用于迭代集合,比如列表或数组,生成一段 sql 代码。对集合进⾏遍历时可以使⽤该标签。<foreach>标签有如下属性:

  • collection:绑定⽅法参数中的集合,如 List,Set,Map或数组对象
  • item:遍历时的每⼀个对象
  • open:语句块开头的字符串
  • close:语句块结束的字符串
  • separator:每次遍历之间间隔的字符串

UserMapper接口:

    int deleteById(List<Integer> ids);

UserMapper.xml: 

        <delete id="deleteById">
                delete from userinfo where id in
                <foreach collection="ids" open="(" close=")" item="id" separator=",">
                        #{id}
                </foreach>
        </delete>

测试: 

    @Test
    void deleteById() {
        List<Integer> list = new ArrayList<Integer>();
        list.add(4);
        list.add(5);
        int ret = userMapper.deleteById(list);
        System.out.println("执行了:"+ret+"条操作");
    }

结果为: 


本期博文到这里就结束了,希望各位有所收获。


微信公众号

今日签到

点亮在社区的每一天
去签到