> 文章列表 > JavaWeb开发 —— MyBatis动态SQL

JavaWeb开发 —— MyBatis动态SQL

JavaWeb开发 —— MyBatis动态SQL

目录

一、XML映射文件

1.  介绍

2.  MyBatisX插件

二、MyBatis动态SQL

1.  if

2.  foreach

3.  sql & include


一、XML映射文件

1.  介绍

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

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

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

//mybatis中文网
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.mybatis.mapper.EmpMapper">
<!--    resultType:单条记录所封装的类型-->
<!--    权限定位名 : 找到对应 -> 右键 -> Copy -> Copy Reference --><select id="list" resultType="com.mybatis.pojo.Emp">select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +"entrydate between #{begin} and #{end} order by update_time desc;</select>
</mapper>

使用Mybatis的注解,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句。
官方说明:https://mybatis.net.cn/getting-started.html

2.  MyBatisX插件

① MybatisX 是一款基于IDEA的快速开发Mybatis的插件,为效率而生。

② 安装:

二、MyBatis动态SQL

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

<select id="getList" resultType="com.mybatis.pojo.Emp">select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +"entrydate between #{begin} and #{end} order by update_time desc;</select>

例如我们之前编写的select语句,where条件是固定的,即使查询时没有指定,也会传递空值null进行查询。而比如我们只想通过name属性进行查询,在查询时后两个条件也会拼接但是传递的是空值null,也是查询不到数据的。

所以我们通过 动态SQL 的三个标签来解决这个问题:

  • <if>
  • <foreach>
  • <sql><include>

1.  if

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

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

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

<!-- 动态查询-->public List<Emp> getList(String name, short gender, LocalDate begin, LocalDate end);<select id="getList" resultType="com.mybatis.pojo.Emp">select *from 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 entrydate between #{begin} and #{end}</if></where>order by update_time desc;</select>

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

需求:动态更新员工信息,如果更新时传递有值,则更新;如果更新时没有传递值,则不更新。

解决方案:动态SQL

//动态更新员工 --- 更新ID为18的员工  username:Tom111,name:汤姆111,gender:2@Testpublic void testUpdate2(){//构建员工对象Emp emp = new Emp();emp.setId(18);emp.setUsername("Tom111");emp.setName("汤姆111");emp.setGender((short)2);emp.setUpdateTime(LocalDateTime.now());//执行更新员工信息操作empMapper.update(emp);
}

更新后其他值没有传参赋值所以均为空值null,这与我们预期结果不一致。

 使用动态SQL解决问题:

<!-- 动态SQL 动态更新 -->public void update2(Emp emp);<update id="update2">update 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>where id = #{id};</set></update>

2.  foreach

在我们之前的学习和设计中,批量删除就会用<foreach>标签。

属性:

  • collection:集合名称
  • item:集合遍历出来的元素/项
  • separator:每一次遍历使用 的分隔符
  • open:遍历开始前拼接的片段
  • close:遍历结束后拼接的片段

// 批量删除员工
// 实现类@Testpublic void testDeleteBuIds(){List<Integer> ids = Arrays.asList(13,14,15);empMapper.delectByIds(ids);}// 接口方法
public void delectByIds(List<Integer> ids);//XML映射文件
<delete id="delectByIds">delete from emp where id in<!--collection:遍历的集合item:遍历出来的元素separator:分隔符open:遍历开始前拼接的sql片段close:遍历结束后拼接的sql片段 --><foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete>

3.  sql & include

问题分析:

<select id="list" resultType="com.mybatis.pojo.Emp">select id, username, password, name, gender, image, job, entrydate, dept_ id, create_ _time, update_ _time from empwhere<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 entrydate between #{begin} and #(end}</if>order by update_ _time desc
</select><select id="getByld" resultType="com.mybatis.pojo.Emp">select id, username, password, name, gender, image, job, entrydate, dept_ id, create_ _time, update_ _time from empwhere id = #{id}
</select>

动态条件查询和根据id查询员工信息,直接利用select * 将所有信息字段罗列出来。而且代码也存在重复冗余,代码复用性低。在Java中我们会将重复代码封装到方法中,需要代码逻辑时直接调用。而在MyBatis动态SQL我们同样可以将重复代码抽取然后在原位置重新引入。


① <sql>:定义可重用的SQL片段,指定唯一标识id属性

② <include>:通过属性refid,指定包含的sql片段。

<sql id="commonSelect">select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_timefrom emp</sql><select id="getList" resultType="com.mybatis.pojo.Emp"><include refid="commonSelect"></include><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 entrydate between #{begin} and #{end}</if></where>order by update_time desc;</select>