菜鸟之路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>
  • 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);
}

我们可以安装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

于是我们将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>

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

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

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);

修改为XML映射动态SQL

<set>:动态地在行首插入SET关键字,并会删掉额外的逗号。(用在update语句中)
    <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>

单元测试

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

        empMapper.update(emp);
    }

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

2.2foreach

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

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

delete from tb_emp where id in (id1,id2,id3,id4)

在EmpMapper中定义接口

//批量删除员工
public void deleteByIds(List<Integer> ids);

建立映射

    <!--批量删除员工-->
    <!--
        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>

单元测试

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

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

2.3sql和include的

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

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

目录
相关文章
|
7月前
|
SQL Java 数据库连接
MyBatis 的映射关系
MyBatis 核心功能之一是映射关系,支持一对一、一对多和多对多三种 ORM 映射。通过实体类与配置文件结合,开发者可灵活实现数据关联,提升数据库操作效率。
392 4
|
8月前
|
SQL XML Java
通过MyBatis的XML配置实现灵活的动态SQL查询
总结而言,通过MyBatis的XML配置实现灵活的动态SQL查询,可以让开发者以声明式的方式构建SQL语句,既保证了SQL操作的灵活性,又简化了代码的复杂度。这种方式可以显著提高数据库操作的效率和代码的可维护性。
476 18
|
8月前
|
SQL Java 数据库连接
SSM相关问题-1--#{}和${}有什么区别吗?--Mybatis都有哪些动态sql?能简述一下动 态sql的执行原理吗?--Spring支持的几种bean的作用域 Scope
在MyBatis中,`#{}`是预处理占位符,可防止SQL注入,适用于大多数参数传递场景;而`${}`是直接字符串替换,不安全,仅用于动态表名、列名等特殊场景。二者在安全性、性能及使用场景上有显著区别。
306 0
|
12月前
|
SQL Java 数据库连接
MyBatis动态SQL字符串空值判断,这个细节99%的程序员都踩过坑!
本文深入探讨了MyBatis动态SQL中字符串参数判空的常见问题。通过具体案例分析,对比了`name != null and name != &#39;&#39;`与`name != null and name != &#39; &#39;`两种写法的差异,指出后者可能引发逻辑混乱。为避免此类问题,建议在后端对参数进行预处理(如trim去空格),简化MyBatis判断逻辑,提升代码健壮性与可维护性。细节决定成败,严谨处理参数判空是写出高质量代码的关键。
1565 0
|
SQL Java 数据库连接
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
|
SQL Java 数据库连接
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
|
12月前
|
JSON 前端开发 Java
深入理解 Spring Boot 中日期时间格式化:@DateTimeFormat 与 @JsonFormat 完整实践
在 Spring Boot 开发中,处理前后端日期交互是一个常见问题。本文通过 **@DateTimeFormat** 和 **@JsonFormat** 两个注解,详细讲解了如何解析前端传来的日期字符串以及以指定格式返回日期数据。文章从实际案例出发,结合代码演示两者的使用场景与注意事项,解决解析失败、时区偏差等问题,并提供全局配置与局部注解的实践经验。帮助开发者高效应对日期时间格式化需求,提升开发效率。
3481 2
|
前端开发 Java API
Swagger接口文档 —— 手把手教学,全方位超详细小白能看懂,百分百能用Java版
本文提供了一份详细的Swagger接口文档生成工具的使用教程,包括了导入依赖、配置类设置、资源映射、拦截器配置、Swagger注解使用、生成接口文档、在线调试页面访问以及如何设置全局参数(如token),旨在帮助Java开发者快速上手Swagger。
10845 0
Swagger接口文档 —— 手把手教学,全方位超详细小白能看懂,百分百能用Java版
|
Java 应用服务中间件 Maven
idea配置本地maven保姆级教程
idea配置本地maven保姆级教程
3395 0
|
存储 JSON NoSQL
[Redis]——RedisTemplate的两种序列化方式
[Redis]——RedisTemplate的两种序列化方式
924 0