MyBatis的强大特性--动态SQL

简介: MyBatis的强大特性--动态SQL


前言

       动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

       例如在注册用户的时候, 提交的表单中肯定有非必填字段, 前端会将拿到的数据送给后端, 但是, 用户在提交的时候, 由于存在非必填字段, 于是用户提交的字段可能是变数, 可能是一个, 两个或者三个, 例如有下面三个字段

  • username
  • password
  • tele
  • age(非必填)
  • sex
  • .....

       除了age都为必填, 这个时候, 前端返回数据给后端, 然后使用sql将其存入数据库, 那么, 在插入的时候

insert into table(username, password, tele, sex, age) values(#{username},#{username}, #{tele}, #{sex}, #{age});

      上面是age传入的时候, 那么试想一下, 如果这个age如果用户没有选择填写呢, 那么insert语句中的age选项就应该被抹除

       使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

       如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

if

    <insert id="insert" parameterType="org.example.model.User" useGeneratedKey
            s="true" keyProperty="id">
        insert into user(
        username,
        password,
        nickname,
        <if test="sex != null">
            sex,
        </if>
        birthday,
        head
        ) values (
        #{username},
        #{password},
        #{nickname},
        <if test="sex != null">
            #{sex},
        </if>
        #{birthday},
        #{head}
        )
    </insert>

       if中有一个test属性, test是判断这个sex项是否存在的标准, 前端传过来的数据会被解析为java对象, 并将属性写入到对象中, 如果对象中的sex属性为空, 那么就代表用户没有传入这个字段, 于是就需要将这个项给抹除.

trim

       上面的情况是只有一个选填项, 但是如果所有的字段, 都可能是选填项, 那么就可以配合trim使用if来解决:

    <insert id="insert" parameterType="org.example.model.User" useGeneratedKeys="true" keyProperty="id">
    insert into user
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="username != null">
            username,
        </if>
        <if test="password != null">
            password,
        </if>
        <if test="nickname != null">
            nickname,
        </if>
        <if test="sex != null">
            sex,
        </if>
        <if test="birthday != null">
            birthday,
        </if>
        <if test="head != null">
            head,
        </if>
        <if test="createTime != null">
            create_time,
        </if>
    </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="username != null">
                #{username},
            </if>
            <if test="password != null">
                #{password},
            </if>
            <if test="nickname != null">
                #{nickname},
            </if>
            <if test="sex != null">
                #{sex},
            </if>
            <if test="birthday != null">
                #{birthday},
            </if>
            <if test="head != null">
                #{head},
            </if>
            <if test="createTime != null">
                #{createTime},
            </if>
        </trim>
    </insert>

  • prefix : 表示整个trim语句块的开头
  • suffix : 表示整个trim语句块的结尾
  • prefixOverrides : 表示整个语句块要去除掉的前缀
  • suffixOverrides : 表示整个语句块中, 要去除掉的后缀, 这个后缀是不计suffix的. 例如trim语句块如下, 那么结束的时候就为 " .... .... head, create_time,)" ,呢么就会忽略 ')', 去除create_time后面的','
<if test="head != null">
head,
</if>
<if test="createTime != null">
create_time,
</if>

上面语句翻译过来就是

isnert into user(username, password, age, sex, ) values(#{username}, #{password}, #{age}, #{sex},)

       需要注意的是, 这里的sex可能为选填, 无论如何, 这个table_name后面的参数和values中的参数, 必定有以 ',' 结尾的内容, 但是这个在sql中是错误语句. 于是使用suffixOverrides将后缀','去除(不包括 suffix =')').

where

       传⼊的⽤户对象,根据属性做 where 条件查询,⽤户对象中属性不为 null 的,都为查询条件。如user.username 为 "a",则查询条件为 where username="a":

UserMapper 接⼝中新增条件查询⽅法:

List<User> selectByCondition(User user);

xml中新增查询语句:

    <select id="selectByCondition" parameterType="org.example.model.User" resultMap="BaseResultMap">
        select id, username, password, nickname, sex, birthday, head, create_time
        from user
        <where>
            <if test="username != null">
                and username=#{username}
            </if>
            <if test="password != null">
                and password=#{password}
            </if>
            <if test="nickname != null">
                and nickname=#{nickname}
            </if>
            <if test="sex != null">
                and sex=#{sex}
            </if>
            <if test="birthday != null">
                and birthday=#{birthday}
            </if>
            <if test="head != null">
                and head=#{head}
            </if>
            <if test="createTime != null">
                and create_time=#{createTime}
            </if>
        </where>
    </select>

       注意: 这里的and一定要写到 column = #{column } 的前面, 也就是:

' and column = #{column } '

       where标签就会自动识别并去除多余的and.

       当然, where也可以使用trim标签和if标签代替.

set

       根据传⼊的⽤户对象属性来更新⽤户数据,可以使⽤标签来指定动态内容

定义mapper接口:

int updateById(User user);

xml:

    <update id="updateById" parameterType="org.example.model.User">
        update user
        <set>
            <if test="username != null">
                username=#{username},
            </if>
            <if test="password != null">
                password=#{password},
            </if>
            <if test="nickname != null">
                nickname=#{nickname},
            </if>
            <if test="sex != null">
                sex=#{sex},
            </if>
            <if test="birthday != null">
                birthday=#{birthday},
            </if>
            <if test="head != null">
                head=#{head},
            </if>
            <if test="createTime != null">
                create_time=#{createTime},
            </if>
        </set>
        where id=#{id}
    </update>

       set会自动去掉末尾的 ','

foreach

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

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

示例:根据多个⽂章 id 来删除⽂章数据

ArticleMapper 中新增接⼝⽅法

int deleteByIds(List<Integer> ids);

       使用List接收, Integer为泛型, 传入的是一个Integer的list集合, 每一个Integer对象对应一个要被删除的文章(Article)

ArticleMapper.xml 中新增删除 sql:

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

in后面其实是可以使用一个多表查询的, 现在这里使用的foreach进行遍历.

  • Collection指明集合的类型
  • itme表示每个每一个对象

然后就遍历成了:

delete from article where id in  (item1, item2, item3 ..... )

这一个个item对象就是list中的Integer对象. 也就是对应的int类型, 与id的类型对应.

目录
相关文章
|
3月前
|
SQL Java 测试技术
3、Mybatis-Plus 自定义sql语句
这篇文章介绍了如何在Mybatis-Plus框架中使用自定义SQL语句进行数据库操作。内容包括文档结构、编写mapper文件、mapper.xml文件的解释说明、在mapper接口中定义方法、在mapper.xml文件中实现接口方法的SQL语句,以及如何在单元测试中测试自定义的SQL语句,并展示了测试结果。
3、Mybatis-Plus 自定义sql语句
|
12天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
1月前
|
SQL Java 数据库连接
mybatis使用四:dao接口参数与mapper 接口中SQL的对应和对应方式的总结,MyBatis的parameterType传入参数类型
这篇文章是关于MyBatis中DAO接口参数与Mapper接口中SQL的对应关系,以及如何使用parameterType传入参数类型的详细总结。
30 10
|
2月前
|
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标签的用法
|
1月前
|
SQL 存储 数据库
SQL学习一:ACID四个特性,CURD基本操作,常用关键字,常用聚合函数,五个约束,综合题
这篇文章是关于SQL基础知识的全面介绍,包括ACID特性、CURD操作、常用关键字、聚合函数、约束以及索引的创建和使用,并通过综合题目来巩固学习。
32 1
|
3月前
|
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/
|
2月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
44 1
|
3月前
|
SQL Java 数据库连接
Mybatis系列之 动态SQL
文章详细介绍了Mybatis中的动态SQL用法,包括`<if>`、`<choose>`、`<when>`、`<otherwise>`、`<trim>`和`<foreach>`等元素的应用,并通过实际代码示例展示了如何根据不同条件动态生成SQL语句。
|
3月前
|
SQL Java 关系型数据库
SpringBoot 系列之 MyBatis输出SQL日志
这篇文章介绍了如何在SpringBoot项目中通过MyBatis配置输出SQL日志,具体方法是在`application.yml`或`application.properties`中设置MyBatis的日志实现为`org.apache.ibatis.logging.stdout.StdOutImpl`来直接在控制台打印SQL日志。
SpringBoot 系列之 MyBatis输出SQL日志
|
3月前
|
SQL 关系型数据库 MySQL
解决:Mybatis-plus向数据库插入数据的时候 报You have an error in your SQL syntax
该博客文章讨论了在使用Mybatis-Plus向数据库插入数据时遇到的一个常见问题:SQL语法错误。作者发现错误是由于数据库字段中使用了MySQL的关键字,导致SQL语句执行失败。解决方法是将这些关键字替换为其他字段名称,以避免语法错误。文章通过截图展示了具体的操作步骤。