JavaWeb笔记——Mybatis的xml映射文件、动态SQL


黑马程序员2023年javaweb网课笔记,自用


tip 1:全限定名/相对地址

指相对地址,右击实体类的名称可以查到
在这里插入图片描述


tip 2:Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ’ ’

  1. 运行报错时从下向上看,找到caused by部分的报错注释
  2. 该报错是SQL语法错误,可以在use near’ '中找到报错的语法位置。

一、XML映射文件基础配置

  1. 理论:xml映射文件可以和注释交叉使用,取决于sql语句的复杂程度和团队需求
    1)@Select等注释配置sql语句:完成简单的增删查改功能
    2)xml文件做sql语句映射:实现复杂的sql功能
  2. 应用规范:
    1)同包同名:XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下。在resources包下创建的目录包,直接使用.来分割是不能达到层级效果的,使用/分割。
    在这里插入图片描述
    在这里插入图片描述

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

mybatis官方入门网址:https://mybatis.org/mybatis-3/zh/getting-started.html
已映射的 SQL 语句配置文件头如下,可以在入门网址中找到。
此处的全限定名一致是指从java包下的相对目录地址

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.liquor.mybatis_01.mapper.EmpMapper">
</mapper>

3)XML映射文件中sql语句的id与Mapper 接口中的方法名一致,并保持返回类型一致。返回类型指单条数据的封装类型,如果是实体类,是该实体类的全限定名。 如,接口中的方法返回类型为List,则resultType为Emp的全限定名com.liquor.mybatis_01.pojo.Emp。

Mapper接口中的方法:

   public List<Emp> selectList(String name,short gender);

xml文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.liquor.mybatis_01.mapper.EmpMapper">
   <select id="selectList" resultType="com.liquor.mybatis_01.pojo.Emp">
       SELECT * from tb_emp where name like concat('%',#{name},'%') and gender = #{gender} >order by update_time desc
   </select>
</mapper>

二、mybatisx插件

  1. 在settinngs安装插件
    在这里插入图片描述

2.1 定位功能

xml文件和接口文件左侧会有图标,单击可以快速切换定位
在这里插入图片描述
在这里插入图片描述

2.2 自动生成接口对应标签

  1. 未配置sql语句的接口会爆红,单击爆红名称,快捷键alt+enter,自动生成
    在这里插入图片描述
  2. 效果:自动生成id和resultType的属性值
    在这里插入图片描述

三、xml映射文件中的动态SQL

  1. 原因:在查询语句中,如果多条件查询(如图,可以通过姓名、性别、入职时间进行查询),则外部输入的条件个数不确定(如,只输入姓名、性别),如果使用固定的sql语句,则会导致查询失败(如,只输入姓名和性别,入职时间会传回一个null值,导致查询失败)。
    在这里插入图片描述

3.1 if 和 where 标签——动态多条件

  1. 理论:
<if>:用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL。
<where>:where 元素只会在子元素有内容的情况下才插入where子句。而且会自动去除子句的开头的AND 或OR。
  1. 实例:
    1)原固定sql语句
SELECT * from tb_emp where name like concat('%',#{name},'%') and gender = #{gender} order by update_time desc

2)动态sql语句在xml中配置

    <select id="selectList" resultType="com.liquor.mybatis_01.pojo.Emp">
        SELECT *
        from tb_emp
        where 
            <if test="name!=null">
                name like concat('%',#{name},'%')
            </if>
            <if test="gender!=null">
                and gender = #{gender}
            </if>
          order by update_time desc
    </select>

3)接口:因为需要给gender赋值为null,此处需要使用Short类型,而非short类型(首字母大小写),否则会报错。

    public List<Emp> selectList(String name,Short gender);

4)测试代码1:当gender为null

    @Test
    public void testSelectList(){
        List<Emp> emps =empMapper.selectList("汤",null);
        System.out.println(emps);
    }

5)结果1:可以看出,执行的sql语句只拼接了name的条件,没有gender
在这里插入图片描述
6)测试2:name为null,结果2:出现sql语法报错,原因是使用当前sql语句时,如果name的条件不拼接,则实际执行sql语句如下,where后面自然衔接了and,出现语法问题。

SELECT * from tb_emp where and gender = #{gender} order by update_time desc

在这里插入图片描述
7)测试2的解决方案:将where字段换成where标签,会自动删除where后紧接的and或者or,如果没有条件符合,则不会显示where,默认为全查询。

    <select id="selectList" resultType="com.liquor.mybatis_01.pojo.Emp">
        SELECT *
        from tb_emp
        <where>
            <if test="name!=null">
                name like concat('%',#{name},'%')
            </if>
            <if test="gender!=null">
                and gender = #{gender}
            </if>
        </where>
          order by update_time desc
    </select>

3.2 set 标签——动态更新

  1. 理论:
<set>:动态地在行首插入 SET 关键字,并会删掉末尾额外的逗号。(用在update语句中)
  1. 实例:只更新传入值非null的数值
    1)原固定sql语句
    @Update("update tb_emp set username = #{username}, name = #{name}, gender = #{gender}, image = #{image}," +
            " job = #{job}, entrydate = #{entrydate}, dept_id = #{deptId},update_time = #{updateTime} " +
            "where id = #{id}")

2)动态sql语句在xml中配置:此处的接口返回值为void,所以不需要配置resultType

    <update id="update">
       update tb_emp
        <set>
            <if test="username!=null">
                username = #{username},
            </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="entrydate!=null">
                entrydate = #{entrydate},
            </if>
            <if test="deptId!=null">
                dept_id = #{deptId},
            </if>
            <if test="updateTime!=null">
                update_time = #{updateTime}
            </if>
        </set>
        where id = #{id}
    </update>

3)接口:

       public void update(Emp emp);

4)测试代码:设置部分值为null

    @Test
    public void testUpdate(){
        Emp emp = new Emp();
        emp.setId(20);
        emp.setUsername("K");
        emp.setName(null);
        emp.setJob(null);
        emp.setEntrydate(LocalDate.of(2001,2,3));
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        emp.setDeptId(1);
        empMapper.update(emp);
    }

5)结果:传入非null的数据被更新
在这里插入图片描述

3.3 foreach 标签——批量操作

  1. 原理:一般和in一起用,类似于循环语句
 <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
 </foreach>
  1. 属性:
    在这里插入图片描述
  2. 实例:根据id批量删除员工:
    1)原固定sql语句
delete from tb_emp where id in (#{id1},#{id2},#{id3})//此处是固定给出了3个id号,没做动态的个数

2)动态sql语句在xml中配置:collections名称与接口形参一致;item与foreach中#{id}一致;separator是传入参数的分隔符,open和close是除数据外的始末片段

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

3)接口:

      public void deleteByIds(List<Integer> ids);

4)测试代码:

    @Test
    public void testDeleteById(){
        List<Integer> ids= Arrays.asList(19,20);
        empMapper.deleteByIds(ids);
    }

5)结果:
在这里插入图片描述

3.4 sql 和 include 标签

  1. 问题:考虑到select查询多个属性值需要罗列属性名称,后期维护困难,所以将高频重复的sql语句段抽取出来封装到sql标签中
  2. 理论:
1) <sql>:定义可重用的 SQL 片段。属性id作为标识符。
2) <include>:属性refid指定sql标签的Id,引入对应的sql片段。该标签可以直接用/自闭环。
  1. 实例:
    1)sql标签抽取的sql片段
    <sql id="EmpAllSelect">
        SELECT id, username, password, name, gender, image, job, entrydate,dept_id, create_time, update_time
        from tb_emp
    </sql>

2)使用include标签引入

    <select id="selectList" resultType="com.liquor.mybatis_01.pojo.Emp">
        <include refid="EmpAllSelect"/>
        <where>
            <if test="name!=null">
                name like concat('%',#{name},'%')
            </if>
            <if test="gender!=null">
                and gender = #{gender}
            </if>
        </where>
          order by update_time desc
    </select>
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值