Data Access 之 MyBatis(四) - Dynamic SQL(下)

简介: Data Access 之 MyBatis(四) - Dynamic SQL

where,自动去除SQL语句中多余的and

在SQL语句中含有多个if判断条件一旦某一个if判断不满足条件,那么这个SQL语句会多出来一个and,这样就会导致SQL执行报错。

将测试方法中给birthDate赋值的代码注销,再次执行测试

51f3552ba22e43afad5aff507ca591d0_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

这种情况下可以使用where标签,自动去除多余的and,修改SQL语句为

<select id="getTeacherList" resultType="com.citi.entity.Teacher">
    select * from t_teacher
    <where>
        <!--test="",编写判断条件 id!= null,取出传入的JavaBean属性中ID的值,判断是否为空-->
        <if test="id!=null">
            id > #{id}
        </if>
        <if test="className!=null">
            and class_name like #{className}
        </if>
        <if test="birthDate!=null">
            and birth_date &lt; #{birthDate}
        </if>
    </where>
</select>
复制代码

再次执行测试

b47d7bd32c01484797827080cebddadd_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

注销id赋值代码,执行测试

image.png

trim,截取字符串

去掉后面的and,判断条件可能条件前或者条件后出现多余的and,条件前出现多余的and可以使用where标签去除,条件后出现的对于的and where标签无能为力,这时可以使用trim标签

修改SQL语句

<select id="getTeacherList" resultType="com.citi.entity.Teacher">
    select * from t_teacher
    <where>
        <!--test="",编写判断条件 id!= null,取出传入的JavaBean属性中ID的值,判断是否为空-->
        <if test="id!=null">
            id > #{id} and
        </if>
        <if test="className!=null">
            class_name like #{className} and
        </if>
        <if test="birthDate!=null">
            birth_date &lt; #{birthDate} and
        </if>
    </where>
</select>
复制代码

注销测试代码中id和birthDate的赋值代码,执行测试

image.png

修改SQL语句

<select id="getTeacherList" resultType="com.citi.entity.Teacher">
    select * from t_teacher
    <trim prefix="where" suffixOverrides="and">
        <!--test="",编写判断条件 id!= null,取出传入的JavaBean属性中ID的值,判断是否为空-->
        <if test="id!=null">
            id > #{id} and
        </if>
        <if test="className!=null">
            class_name like #{className} and
        </if>
        <if test="birthDate!=null">
            birth_date &lt; #{birthDate} and
        </if>
    </trim>
</select>
复制代码
  • prefix="":前缀,为trim标签包裹的SQL增加一个前缀
  • prefixOverrides="":去除整体字符串前多余的字符
  • suffix="":为整体添加一个后缀
  • suffixOverrides="":去除整体字符串后面多余的字符 再次执行测试

image.png

建议查询条件就放在where标签中,and关键字放在条件前面,一旦条件判断为false,where会自动去除多余的and关键字

foreach,遍历集合

TeacherMapper接口中新增一个方法,根据传入的ids集合查询所有的Teacher

List<Teacher> getTeacherListByIds(@Param("ids")List<Integer> ids);
复制代码

在TeacmerMapper.xml中增加方法的SQL语句

<select id="getTeacherListByIds" resultType="com.citi.entity.Teacher">
    select * from t_teacher where id IN
    <foreach collection="ids" item="id_item" separator="," open="(" close=")">
        #{id_item}
    </foreach>
</select>
复制代码
  • collection:指要遍历的集合的key
  • open:以什么开始
  • close:以什么结束
  • separator:遍历元素的分隔符
  • item:遍历的元素的变量名
  • index:索引
  • 遍历List:
  • index:保存了当前元素的索引
  • item:保存了当前元素的值
  • 遍历Map:
  • index:保存当前元素的key
  • item:保存当前元素的值

新增测试方法

@Test
public void getTeacherListByIds() {
    TeacherMapper teacherMapper = openSession.getMapper(TeacherMapper.class);
    List<Integer> ids = Arrays.asList(1,2,3);
    List<Teacher> teacherList = teacherMapper.getTeacherListByIds(ids);
    System.out.println(teacherList);
}
复制代码

执行测试

image.png

choose,分支选择,相当于if-else

TeacherMapper接口中新增一个方法

List<Teacher> getTeacherListByChoose(Teacher teacher);
复制代码

在TeacherMapper.xml中增加SQL语句

<select id="getTeacherListByChoose" resultType="com.citi.entity.Teacher">
    select * from t_teacher
    <where>
        <choose>
            <when test="id!=null">
                id=#{id}
            </when>
            <when test="className!=null and !className.equals(&quot;&quot;)">
                class_name = #{className}
            </when>
            <when test="birthDate!=null">
                birth_date = #{birthDate}
            </when>
            <otherwise>
                1=1
            </otherwise>
        </choose>
    </where>
</select>
复制代码
@Test
public void getTeacherListByChoose() {
    TeacherMapper teacherMapper = openSession.getMapper(TeacherMapper.class);
    Teacher teacher = new Teacher();
    teacher.setId(1);
    teacher.setClassName("三年二班");
    // teacher.setBirthDate(new Date());
    List<Teacher> teacherList = teacherMapper.getTeacherListByChoose(teacher);
    System.out.println(teacherList);
}
复制代码

执行测试

image.png

id、className、birthDate赋值代码全部注销

image.png

choose可以实现条件查询条件的分支选择,if可以实现查询条件的叠加

set,实现动态更新

实现动态更新,自动去除逗号“,”

TeacherMapper中新增方法

int updateTeacher(Teacher teacher);
复制代码

在TeacherMapper.xml中新增SQL语句

<update id="updateTeacher">
    update t_teacher
    <set>
        <if test="teacherName!=null and !teacherName.equals(&quot;&quot;)">
            teacher_name = #{teacherName},
        </if>
        <if test="className!=null and !className.equals(&quot;&quot;)">
            class_name = #{className},
        </if>
        <if test="address!=null and !address.equals(&quot;&quot;)">
            address = #{address},
        </if>
        <if test="birthDate!=null">
            birth_date = #{birthDate}
        </if>
    </set>
    <where>
        id = #{id}
    </where>
</update>
复制代码

增加测试方法

@Test
public void updateTeacher() {
    TeacherMapper teacherMapper = openSession.getMapper(TeacherMapper.class);
    Teacher teacher = new Teacher();
    teacher.setId(1);
    teacher.setClassName("三年三班");
    teacher.setTeacherName("Tony Stark");
    teacher.setBirthDate(new Date());
    teacherMapper.updateTeacher(teacher);
    Teacher updateTeacher = teacherMapper.getTeacherById(1);
    System.out.println(updateTeacher);
}
复制代码

执行测试

image.png

include与sql,抽取可重用的语句

以getTeacherListByIds方法的SQL映射语句为例

<!--抽取的可重复使用的SQL-->
<sql id="select*">select * from t_teacher</sql>
<select id="getTeacherListByIds" resultType="com.citi.entity.Teacher">
    <!--引用抽取的SQL-->
    <include refid="select*"></include> where id IN
    <foreach collection="ids" item="id_item" separator="," open="(" close=")">
        #{id_item}
    </foreach>
</select>


相关文章
|
SQL Java 数据库连接
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
|
7月前
|
SQL XML Java
通过MyBatis的XML配置实现灵活的动态SQL查询
总结而言,通过MyBatis的XML配置实现灵活的动态SQL查询,可以让开发者以声明式的方式构建SQL语句,既保证了SQL操作的灵活性,又简化了代码的复杂度。这种方式可以显著提高数据库操作的效率和代码的可维护性。
461 18
|
11月前
|
SQL Java 数据库连接
MyBatis动态SQL字符串空值判断,这个细节99%的程序员都踩过坑!
本文深入探讨了MyBatis动态SQL中字符串参数判空的常见问题。通过具体案例分析,对比了`name != null and name != &#39;&#39;`与`name != null and name != &#39; &#39;`两种写法的差异,指出后者可能引发逻辑混乱。为避免此类问题,建议在后端对参数进行预处理(如trim去空格),简化MyBatis判断逻辑,提升代码健壮性与可维护性。细节决定成败,严谨处理参数判空是写出高质量代码的关键。
1530 0
|
7月前
|
SQL Java 数据库连接
SSM相关问题-1--#{}和${}有什么区别吗?--Mybatis都有哪些动态sql?能简述一下动 态sql的执行原理吗?--Spring支持的几种bean的作用域 Scope
在MyBatis中,`#{}`是预处理占位符,可防止SQL注入,适用于大多数参数传递场景;而`${}`是直接字符串替换,不安全,仅用于动态表名、列名等特殊场景。二者在安全性、性能及使用场景上有显著区别。
286 0
|
10月前
|
SQL XML Java
菜鸟之路Day35一一Mybatis之XML映射与动态SQL
本文介绍了MyBatis框架中XML映射与动态SQL的使用方法,作者通过实例详细解析了XML映射文件的配置规范,包括namespace、id和resultType的设置。文章还对比了注解与XML映射的优缺点,强调复杂SQL更适合XML方式。在动态SQL部分,重点讲解了`&lt;if&gt;`、`&lt;where&gt;`、`&lt;set&gt;`、`&lt;foreach&gt;`等标签的应用场景,如条件查询、动态更新和批量删除,并通过代码示例展示了其灵活性与实用性。最后,通过`&lt;sql&gt;`和`&lt;include&gt;`实现代码复用,优化维护效率。
1022 5
|
SQL Java 数据库连接
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
|
SQL 缓存 Java
框架源码私享笔记(02)Mybatis核心框架原理 | 一条SQL透析核心组件功能特性
本文详细解构了MyBatis的工作机制,包括解析配置、创建连接、执行SQL、结果封装和关闭连接等步骤。文章还介绍了MyBatis的五大核心功能特性:支持动态SQL、缓存机制(一级和二级缓存)、插件扩展、延迟加载和SQL注解,帮助读者深入了解其高效灵活的设计理念。
|
SQL XML Java
六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性
六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性
419 0
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")