菜鸟之路Day35一一Mybatis之XML映射与动态SQL

简介: 本文介绍了MyBatis框架中XML映射与动态SQL的使用方法,作者通过实例详细解析了XML映射文件的配置规范,包括namespace、id和resultType的设置。文章还对比了注解与XML映射的优缺点,强调复杂SQL更适合XML方式。在动态SQL部分,重点讲解了`<if>`、`<where>`、`<set>`、`<foreach>`等标签的应用场景,如条件查询、动态更新和批量删除,并通过代码示例展示了其灵活性与实用性。最后,通过`<sql>`和`<include>`实现代码复用,优化维护效率。

菜鸟之路Day35一一Mybatis之XML映射与动态SQL

作者:blue

时间:2025.5.26

0.概述

内容学习自黑马程序员BV1m84y1w7Tb

1.XML映射文件

配置XML映射文件必须遵循以下三个规范

规范:

XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)

XML映射文件的namespace属性为Mapper接口全限定名一致

XML映射文件sql语句的id与Mapper接口中的方法名一周,并保持返回类型一致

在src/main/resources/com/bluening/mybatis_demo/mapper配置EmpMapper.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.bluening.mybatis_demo.mapper.EmpMapper">
    <select id="getEmpBy" resultType="com.bluening.mybatis_demo.pojo.Emp">
        select * from tb_emp where name like concat('%',#{name},'%') and
            gender=#{gender} and entry_time between #{begin} and #{end}
            order by update_time desc
    </select>
</mapper>
AI 代码解读
  • namespace:必须与 Mapper 接口的全限定名一致,确保绑定。
  • id:对应接口中的方法名(getEmpBy)。
  • resultType:指定 SQL 结果映射的目标类(Emp)。

在src/main/java/com/bluening/mybatis_demo/mapper/EmpMapper编写接口

@Mapper
public interface EmpMapper {
   
    //根据条件查询员工信息
    public List<Emp> getEmpBy(String name, int gender, LocalDateTime begin, LocalDateTime end);
}
AI 代码解读

我们可以安装MyBatisX插件,让我们能够更加轻松的找到对应的映射关系,提高开发效率

image-20250528072247090.png

基于注解VS基于XML映射

使用注解映射简单语句会使代码更加简洁,但对于稍微复杂一点的语句,Java注解不仅力不从心,还会让你本就复杂的SQL语句更加混乱不堪。因此,如果你需要做一些很复杂的操作,最好用XML来映射语句。

选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML的语句映射方式间自由移植和切换。

2.动态SQL

随着用户的输入或者外部条件变化而变化的SQL语句,我们称为动态SQL

2.1if

<if>:用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL。

<where>:where元素只会在子元素有内容得情况下才插入where子句。而且会自动去除子句的开头的AND或OR
AI 代码解读

于是我们将XML映射文件中的SQL语句修改成下面这样

    <select id="getEmpBy" resultType="com.bluening.mybatis_demo.pojo.Emp">
        select *
        from tb_emp
        <where>
            <if test="name != null">
                name like concat('%', #{name}, '%')
            </if>
            <if test="gender != null">
                and gender = #{gender}
            </if>
            <if test="begin != null and end != null">
                and entry_time between #{begin} and #{end}
            </if>
        </where>
        order by update_time desc
    </select>
AI 代码解读

接下来我们调整输入的参数,发现SQL语句的建立会动态变化

//输入
List<Emp> emplist =empMapper.getEmpBy("b",1,null,null);
AI 代码解读

image-20250528080316892.png

案例:完善更新员工功能,修改为动态更新员工数据信息

在我们原始的更新操作中,我们写死更新的字段,导致我们进行部分更新的时候,会导致全体更新,若那个字段为空值,那么原有的值就会被清除掉变为空值,这时我们就可以利用动态SQL来完善更新功能

//更新用户操作
    @Update("update tb_emp set username=#{username},password=#{password},name=#{name},gender=#{gender},image=#{image}," +
            "job=#{job},entry_time=#{entry_time},update_time=#{update_time},dept_id=#{dept_id} " +
            "where id=#{id}")
    public void update(Emp emp);
AI 代码解读

修改为XML映射动态SQL

<set>:动态地在行首插入SET关键字,并会删掉额外的逗号。(用在update语句中)
AI 代码解读
    <update id="update">
        update tb_emp
        <set>
            <if test="username != null">
                username=#{username},
            </if>
            <if test="password != null">
                password=#{password},
            </if>
            <if test="name != null">
                name=#{name},
            </if>
            <if test="gender != null">
                gender=#{gender},
            </if>
            <if test="image != null">
                image=#{image},
            </if>
            <if test="job != null">
                job = #{job},
            </if>
            <if test="entry_time != null">
                entry_time=#{entry_time},
            </if>
            <if test="update_time != null">
                update_time=#{update_time},
            </if>
            <if test="dept_id != null">
                dept_id=#{dept_id}
            </if>
        </set>
        where id=#{id}
    </update>
AI 代码解读

单元测试

    @Test
    public void testUpdate() {
   
        Emp emp = new Emp();
        emp.setId(16);//指定要修改的对象的id
        emp.setUsername("red");

        empMapper.update(emp);
    }
AI 代码解读

可见这里的内容被动态修改了
image-20250528085944673.png

2.2foreach

foreach标签主要用于一些批量操作,以下以批量删除员工为例子

批量删除员工原有的SQL语句为

delete from tb_emp where id in (id1,id2,id3,id4)
AI 代码解读

在EmpMapper中定义接口

//批量删除员工
public void deleteByIds(List<Integer> ids);
AI 代码解读

建立映射

    <!--批量删除员工-->
    <!--
        collection:遍历的集合,注意与接口中的参数同名
        item:遍历出来的元素
        separator:分隔符
        open:遍历开始前拼接的SQL片段
        close:遍历结束后拼接的SQL片段
    -->
    <delete id="deleteByIds">
        delete from tb_emp where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
        </foreach>
    </delete>
AI 代码解读

单元测试

@Test
public void testDeleteByIds() {
   
    List<Integer> ids = Arrays.asList(1, 2, 3);
    empMapper.deleteByIds(ids);
}
AI 代码解读

可以看见批量删除的语句被创建出来
image-20250528092830399.png

2.3sql和include的

代码复用性差如果后期表结构有所修改,需要对所有字段进行修改
image-20250528093227021.png

这时我们的想法是抽取相同代码封装,然后再在其具体需要使用的位置引用,这时就可以利用sql标签和include标签
image-20250528093555935.png

目录
相关文章
MyBatis动态SQL字符串空值判断,这个细节99%的程序员都踩过坑!
本文深入探讨了MyBatis动态SQL中字符串参数判空的常见问题。通过具体案例分析,对比了`name != null and name != &#39;&#39;`与`name != null and name != &#39; &#39;`两种写法的差异,指出后者可能引发逻辑混乱。为避免此类问题,建议在后端对参数进行预处理(如trim去空格),简化MyBatis判断逻辑,提升代码健壮性与可维护性。细节决定成败,严谨处理参数判空是写出高质量代码的关键。
439 0
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
152 0
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
MyBatis映射文件深入--动态sql
MyBatis映射文件深入--动态sql
165 0
mybatis的注解开发之三种动态sql
mybatis的注解开发之三种动态sql
141 0
MyBatis实现动态SQL更新
1. 复杂一点,通过 MyBatis 的拦截器机制,在 SQL 拼接的 prepare 阶段修改 SQL 语句,实现动态 SQL。 考虑到拦截器机制不需要修改过多代码,因此本文博主将带领大家学习如何利用 MyBatis 拦截器机制来优雅的实现这个需求。
352 0
mybatis动态SQL常用语法总结
MyBatis 使用 OGNL 表达式语言处理动态SQL,如 `if` 标签进行条件判断,`choose`、`when`、`otherwise` 实现多条件选择,`where`、`set` 管理SQL关键字,`trim` 提供通用修剪功能,`foreach` 遍历集合数据。`sql` 和 `include` 用于代码重用,`selectKey` 处理插入后的返回值。参数传递支持匿名、具名、列表、Map、Java Bean和JSON方式。注意SQL转义及使用合适的jdbcType映射Java类型。