目录
一、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 mapper
PUBLIC "-//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
@Test
public 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:遍历结束后拼接的片段
// 批量删除员工
// 实现类
@Test
public 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 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>
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 emp
where 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_time
from 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>