【MyBatis】动态SQL

发布于:2025-03-06 ⋅ 阅读:(16) ⋅ 点赞:(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+"条操作");
    }

结果为: 


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


网站公告

今日签到

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