【JavaEE进阶】 MyBatis之动态SQL

简介: 【JavaEE进阶】 MyBatis之动态SQL


🌲动态SQL

动态SQL是Mybatis的强⼤特性之⼀,通过一系列标签能够完成不同条件下不同的sql拼接。

接下来为大家介绍一些标签来完成sql拼接

首先我们准备数据库userinfo表如下:

🍃< if >标签

在我们实际生活中,当我们在注册时,有时候会面临以下情况

注册分为两种字段:必填字段和⾮必填字段

那如果在添加⽤⼾的时候有不确定的字段传⼊,程序应该如何实现呢?

这个时候就需要使⽤动态标签来判断了,⽐如添加的时候性别gender(性别)为⾮必填字段,具体实现如下

我们这里先采用xml方式进行操作:

接口定义如下:

Integer insertUserByCondition(UserInfo userInfo);

XML代码实现:

<insert id="insertUserByCondition">
    INSERT INTO userinfo (
    username,
    password,
    age,
    <if test="gender != null">
        gender,
    </if>
    phone)
    VALUES (
    #{username},
    #{password},
    #{age},
    <if test="gender != null">
        #{gender},
    </if>
    #{phone})
</insert>

使用测试单元进行测试:

@Test
void insertUserByCondition() {
    UserInfo userInfo = new UserInfo();
    userInfo.setUsername("天帅星");
    userInfo.setPassword("123");
    userInfo.setAge(20);
    //userInfo.setGender(1);
    userInfo.setPhone("123456789");
    int count = dynamicSqlMapper.insertUserByCondition(userInfo);
    System.out.println("改变行数为:" + count);
}

启动测试单元:

我们可以看到,查询字段已经没有gender选项了

我们再次查询数据库,看是否插入成功

我们可以看到查询成功。

如果我们选择使用注解的方式的话,我们需要把上⾯SQL(包括标签),使⽤ 标签括起来就可以

使用如下:

@Insert("<script>" +
        "INSERT INTO userinfo (username,`password`,age," +
        "<if test='gender!=null'>gender,</if>" +
        "phone)" +
        "VALUES(#{username},#{password},#{age}," +
        "<if test='gender!=null'>#{gender},</if>" +
        "#{phone})"+
        "</script>")
Integer insert(UserInfo userInfo);

测试单元代码如下:

@Test
void insert() {
    UserInfo userInfo = new UserInfo();
    userInfo.setUsername("koukou星");
    userInfo.setPassword("1231");
    userInfo.setAge(22);
    //userInfo.setGender(1);
    userInfo.setPhone("1234");
    int count = dynamicSqlMapper.insertUserByCondition(userInfo);
    System.out.println("改变行数为:" + count);
}

启动测试单元:

我们可以发现,与上面使用XML效果是一样的。

查验数据库是否插入成功:

也插入成功

但是呢,博主这里推荐使用XML方式,因为不容易出错。接下来博主的演示也全部使用XML的方式。

🌳< trim >标签

上面的插⼊⽤⼾功能,只是有⼀个gender字段可能是选填项,如果有多个字段,就会出现问题。

比如以下程序:

<insert id="insert2">
    INSERT INTO userinfo(
        <if test="username !=null">
            username,
        </if>
        <if test="password !=null">
            `password`,
        </if>
        <if test="age != null">
            age,
        </if>
        <if test="gender != null">
            gender,
        </if>
        <if test="phone != null">
            phone
        </if>)
    VALUES(
        <if test="username !=null">#{username},
        </if><if test="
    password !=null">#{password},
        </if>
        <if test="age != null">
            #{age},
        </if>
        <if test="gender != null">
            #{gender},
        </if>
        <if test="phone != null">
            #{phone}
        </if>)
</insert>

测试单元代码如下:

@Test
void insert2() {
    UserInfo userInfo = new UserInfo();
    userInfo.setUsername("天仇星");
    userInfo.setPassword("11");
    userInfo.setAge(33);
    userInfo.setGender(1);
    //userInfo.setPhone("1234");
    int count = dynamicSqlMapper.insert2(userInfo);
    System.out.println("改变行数为:" + count);
}

启动测试单元

我们发现了报错,上面的sql语句后面多了一个 导致查询失败

这时候我们就需要使用标签结合标签,对多个字段都采取动态⽣成的⽅式

< trim >标签中有如下属性:

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

那么上述问题代码便可以修改如下:

<insert id="insert2">
    INSERT INTO userinfo
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="username !=null">
            username,
        </if>
        <if test="password !=null">
            `password`,
        </if>
        <if test="age != null">
            age,
        </if>
        <if test="gender != null">
            gender,
        </if>
        <if test="phone != null">
            phone
        </if>
    </trim>
    VALUES
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="username !=null">#{username},
        </if><if test="
    password !=null">#{password},
        </if>
        <if test="age != null">
            #{age},
        </if>
        <if test="gender != null">
            #{gender},
        </if>
        <if test="phone != null">
            #{phone}
        </if>
    </trim>
</insert>

在以上sql动态解析时,会将第⼀个部分做如下处理:

  • 基于 prefix 配置,开始部分加上 (
  • 基于 suffix 配置,结束部分加上 )
  • 多个组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于suffixOverrides 配置去掉最后⼀个 ,

🎍< where >标签

当我们需要对多个字段进行查询时。

需求:传⼊的⽤⼾对象,根据属性做where条件查询,⽤⼾对象中属性不为 null 的,都为查询条件.如username为"a",则查询条件为where username=“a”

如果我们只使用上面的两种标签,是无法达到效果的。这时候就需要where标签了

XML相关代码如下:

<select id="select" resultType="com.example.demo.model.UserInfo">
select id, username, age, gender, phone, delete_flag, create_time, update_time
from userinfo
    <where>
    <if test="age != null">
        and age = #{age}
    </if>
    <if test="gender != null">
        and gender = #{gender}
    </if>
        <if test="deleteFlag != null">
            and delete_flag = #{deleteFlag}
        </if>
    </where>
</select>

< where > 只会在⼦元素有内容的情况下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的AND或OR

🍀< set >标签

需求:根据传⼊的⽤⼾对象属性来更新⽤⼾数据,可以使⽤< set >标签来指定动态内容.

<update id="update">
    update userinfo
    <set>
    <if test="username != null">
        username = #{username},
    </if>
        <if test="age != null">
            age = #{age},
        </if>
        <if test="deleteFlag != null">
            delete_flag = #{deleteFlag},
        </if>
    </set>
    where id = #{id}
</update>

< set> :动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号.(⽤于update语句中)

🌴< foreach >标签

对集合进⾏遍历时可以使⽤该标签。标签有如下属性:

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

需求:根据多个userid,删除⽤⼾数据

比如我们又以下接口:

void deleteByIds(List<Integer> ids);

那么我们批量删除的语句就如下:

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

🎋< include >标签

在xml映射⽂件中配置的SQL,有时可能会存在很多重复的⽚段,此时就会存在很多冗余的代码

我们可以对重复的代码⽚段进⾏抽取,将其通过 < sql > 标签封装到⼀个SQL⽚段,然后再通过< include > 标签进⾏引⽤。

  • < sql > :定义可重⽤的SQL⽚段
  • < include > :通过属性refid,指定包含的SQL⽚段

抽取如下:

<sql id="allColumn">
  id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>

通过 < include > 标签在原来抽取的地⽅进⾏引⽤。操作如下:

<select id="queryAllUser" resultMap="BaseMap">
  select 
  <include refid="allColumn"></include>
  from userinfo
</select>

⭕总结

关于《【JavaEE进阶】 MyBatis之动态SQL》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

相关文章
|
11天前
|
SQL XML Java
mybatis实现动态sql
MyBatis的动态SQL功能为开发人员提供了强大的工具来应对复杂的查询需求。通过使用 `<if>`、`<choose>`、`<foreach>`等标签,可以根据不同的条件动态生成SQL语句,从而提高代码的灵活性和可维护性。本文详细介绍了动态SQL的基本用法和实际应用示例,希望对您在实际项目中使用MyBatis有所帮助。
44 11
|
1月前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
1月前
|
SQL Java 数据库连接
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
|
2月前
|
SQL Java 数据库连接
mybatis使用四:dao接口参数与mapper 接口中SQL的对应和对应方式的总结,MyBatis的parameterType传入参数类型
这篇文章是关于MyBatis中DAO接口参数与Mapper接口中SQL的对应关系,以及如何使用parameterType传入参数类型的详细总结。
59 10
|
3月前
|
SQL XML Java
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
文章介绍了MyBatis中动态SQL的用法,包括if、choose、where、set和trim标签,以及foreach标签的详细使用。通过实际代码示例,展示了如何根据条件动态构建查询、更新和批量插入操作的SQL语句。
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
|
4月前
|
SQL Java 数据库连接
Mybatis系列之 Error parsing SQL Mapper Configuration. Could not find resource com/zyz/mybatis/mapper/
文章讲述了在使用Mybatis时遇到的资源文件找不到的问题,并提供了通过修改Maven配置来解决资源文件编译到target目录下的方法。
Mybatis系列之 Error parsing SQL Mapper Configuration. Could not find resource com/zyz/mybatis/mapper/
|
3月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
70 1
|
4月前
|
SQL Java 数据库连接
Mybatis系列之 动态SQL
文章详细介绍了Mybatis中的动态SQL用法,包括`<if>`、`<choose>`、`<when>`、`<otherwise>`、`<trim>`和`<foreach>`等元素的应用,并通过实际代码示例展示了如何根据不同条件动态生成SQL语句。
|
4月前
|
SQL Java 关系型数据库
SpringBoot 系列之 MyBatis输出SQL日志
这篇文章介绍了如何在SpringBoot项目中通过MyBatis配置输出SQL日志,具体方法是在`application.yml`或`application.properties`中设置MyBatis的日志实现为`org.apache.ibatis.logging.stdout.StdOutImpl`来直接在控制台打印SQL日志。
SpringBoot 系列之 MyBatis输出SQL日志
|
2月前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
152 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。