动态sql
动态sql类似于jsp中的JSTL表达式,可以在sql中嵌套判断语句
环境搭建
员工类、部门类
public class Department {
private Integer id;
private String d_name;
private List<Employee> emps;
}
public class Employee {
private Integer id;
private String lastName;
private String gender;
private String email;
private Department department;
}
if标签
场景:根据提供的员工信息查找员工,举例:只给了id通过id查找,给了id和lastname根据两者一起查找
<!--List<Employee> getEmpsDynamicForIf(Employee employee);-->
<select id="getEmpsDynamicForIf" resultType="com.yellowstar.mybatis.bean.Employee">
select * from employee
<!--
如果不使用where标签,当id为null时,sql语句会报错变成where and last_name....
当然也可以通过在where后面加上1=1恒成立的语句解决
where标签作用:可以剔除第一条判断语句前的and
-->
<where>
<!--test中填写判断条件-->
<if test="id!=null">
id = #{id}
</if>
<if test="lastName!=null">
and last_name like #{lastName}
</if>
<if test="gender!=null">
and gender = #{gender}
</if>
<if test="email!=null">
and email = #{email}
</if>
</where>
</select>
有些同学就有一些自己独特的习惯,喜欢讲and放在语句后面,如下,当lastname存在,gender不存在时sql语句会报错
日志输出:select * from employee WHERE last_name like ? and
mybatis为我们提供了trim标签,可以自定义字符串截取
<select id="getEmpsDynamicForTrim" resultType="com.yellowstar.mybatis.bean.Employee">
select * from employee
<where>
<if test="id!=null">
id = #{id} and
</if>
<if test="lastName!=null">
last_name like #{lastName} and
</if>
<if test="gender!=null">
gender = #{gender} and
</if>
<if test="email!=null">
email = #{email}
</if>
</where>
</select>
trim标签
trim标签有4个属性值
- prefix:前缀,在拼接完成的语句前加上信息
- prefixOverrides:去掉一个判断语句中的sql语句前面多余的内容
- suffix:后缀,在拼接完成的语句后加上信息
- suffixOverrides:去掉一个判断语句中的sql语句后面面多余的内容
<!--List<Employee> getEmpsDynamicForTrim(Employee employee);-->
<select id="getEmpsDynamicForTrim" resultType="com.yellowstar.mybatis.bean.Employee">
select * from employee
<trim prefix="where" suffixOverrides="and">
<if test="id!=null">
id = #{id} and
</if>
<if test="lastName!=null">
last_name like #{lastName} and
</if>
<if test="gender!=null">
gender = #{gender} and
</if>
<if test="email!=null">
email like #{email}
</if>
</trim>
</select>
choose标签
场景:与上面场景不同的是,当我们查找员工信息时,如果给了id就根据id查找,没有id在判断有没有name,有的话根据name查找,一次类推,如果什么条件都没有,执行查找所有员工
这里使用到choose标签,个人理解为此标签有点像if…else if…else…
<select id="getEmpsDynamicForChoose" resultType="com.yellowstar.mybatis.bean.Employee">
select * from employee
<where>
<choose>
<when test="id!=null">
id = #{id}
</when>
<when test="lastName!=null">
last_name like #{lastName}
</when>
<when test="gender!=null">
gender = #{gender}
</when>
<when test="email!=null">
email like #{email}
</when>
<otherwise>
<!--如果都不匹配-->
</otherwise>
</choose>
</where>
</select>
set标签
set用于更新数据,注意更新时要手动提交数据
场景:之前在更新一条员工信息时,使用的是全部更新,现在的需求是如果lastname传过来,就更新lastname,反之则不更新
<!--void updateEmpForSet(Employee employee);-->
<update id="updateEmpForSet">
update employee
<set>
<if test="lastName!=null">
last_name = #{lastName},
</if>
<if test="gender!=null">
gender = #{gender},
</if>
<if test="email!=null">
email = #{email}
</if>
</set>
where id = #{id}
</update>
foreach标签
foreach见名知意,是用来循环的
场景一:根据所提供的一个集合(集合中是id值),来查找符合id的员工
先来写一下sql语句(建议每次在mybatis中写sql之前,都先将sql写在数据库工具中试试看),其中的1,2,5就是传入的集合中的每一个参数,需要使用foreach标签遍历这个集合
select * from employee where id in (1,2,5)
<!--List<Employee> getEmpsDynamicForeach(ArrayList<Integer> ids);-->
<select id="getEmpsDynamicForeach" resultType="com.yellowstar.mybatis.bean.Employee">
select * from employee where id in
<!--
collection:传过来的集合对象,如果是list集合的话填list
item:当前遍历的对象
open:遍历拼接完成的语句前添加信息
close:遍历拼接完成的语句后添加信息
separator:分隔符,每一项之间用逗号分隔
-->
<foreach collection="list" item="emp_id" open="(" close=")" separator=",">
#{emp_id}
</foreach>
</select>
场景二:批量插入员工数据
这里我们遍历map集合,如果是map集合,要在接口形参前标识@Param注解,设置map集合的参数名,collection要使用该参数名
<!--void insertEmps(@Param("emps") Map<String,Object> emps);-->
<!-- insert into employee (last_name,gender,email) VALUES (?,?,?) , (?,?,?) -->
<insert id="insertEmps">
insert into employee (last_name,gender,email,d_id) VALUES
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.gender},#{emp.email},#{emp.department.id})
</foreach>
</insert>
mybatis也为我们提供了内置参数,可以不用设置注解,只需要使用_parameter参数即可
_parameter:
如果是单个参数:代表整个参数
如果参数被封装为一个map,_parameter就代表这个map
<!--void insertEmps(@Param("emps") Map<String,Object> emps);-->
<!-- insert into employee (last_name,gender,email) VALUES (?,?,?) , (?,?,?) -->
<insert id="insertEmps">
insert into employee (last_name,gender,email,d_id) VALUES
<foreach collection="_parameter" item="emp" separator=",">
(#{emp.lastName},#{emp.gender},#{emp.email},#{emp.department.id})
</foreach>
</insert>
_databaseId
如果在全局文件中设置了databaseIdProvider标签,_databaseId就代表当前数据库的别名
bind标签
bind
元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文。比如:
<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>
sql标签
在实际开发过程中,查询语句建议见每个字段的名称写出来,而不是用*代替,而有些语句使用的都是同一段字段名,这时候可以使用sql标签,使用的时候引用即可
原xml中如下配置,我们希望id,last_name,gender,email,d_id可以抽取出来,方便其他语句引用
<!--List<Employee> getEmpsDynamicForIf(Employee employee);-->
<select id="getEmpsDynamicForIf" resultType="com.yellowstar.mybatis.bean.Employee">
select id,last_name,gender,email,d_id from employee
<where>
<if test="id!=null">
id = #{id}
</if>
<if test="lastName!=null">
and last_name like #{lastName}
</if>
<if test="gender!=null">
and gender = #{gender}
</if>
<if test="email!=null">
and email = #{email}
</if>
</where>
</select>
可以修改为以下这种写法
<!--List<Employee> getEmpsDynamicForIf(Employee employee);-->
<select id="getEmpsDynamicForIf" resultType="com.yellowstar.mybatis.bean.Employee">
select
<include refid="column"></include>
from employee
<where>
<if test="id!=null">
id = #{id}
</if>
<if test="lastName!=null">
and last_name like #{lastName}
</if>
<if test="gender!=null">
and gender = #{gender}
</if>
<if test="email!=null">
and email = #{email}
</if>
</where>
</select>
<sql id="column">
id,last_name,gender,email,d_id
</sql>