学习之前
进行数据库查询时,有很多参数并不需要传入或没有值传入,具体情况随用户提交的请求确定。当查询条件不确定是,后端应该如何输入最终的SQL语句呢?这时候,MyBatis动态语句便出现了!
动态 SQL 是 MyBatis 的强大特性之一。使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
一、if和where标签
动态SQL最常见的情景是根据输入条件,选择where语句或if语句。
public interface EmployeeMapper {
// 根据员工的姓名和工资查询员工的信息
// 如果传入属性,则判断相等;如果不传入参数,则不加where条件
List<Employee> query(@Param("name") String name,@Param("salary") Double salary);
}
<select id="query" resultType="com.landy.pojo.Employee">
select emp_name , emp_salary from t_emp
<where>
<if test="name != null">
emp_name = #{name}
</if>
<if test="salary != null and salary > 100">
and emp_salary = #{salary}
</if>
</where>
</select>
<if> 标签:判断test=""内部条件是否成立,即该参数是否传入,或该参数是否满足某一条件。大于号用>代替,小于<号用代替
<where> 标签:当条件只有部分满足且没有where标签时,可能出现错误。
- 当第二个条件满足,第一个条件不满足,出现...where and...语法错误
- 若条件都不满足,出现...where语法错误
故需要where标签动态添加where关键字:
- 自动添加where关键字。where标签内部,有任何一个<if>标签满足则自动添加。
二、set标签
<set>标签主要用于更新操作
// 根据员工id更新员工数据,只有传入的name和salary都不为空时才更新
int update(@Param("id") Integer id, @Param("name") String name, @Param("salary") Double salary);
<update id="update">
update t_emp
<set>
<if test="name !=null">
emp_name = #{name}
</if>
<if test="salary != null">
,emp_salary = #{salary}
</if>
</set>
where emp_id = #{id}
</update>
<set>标签作用与<where>标签相似,用于动态添加set关键字。
三、trim标签
动态添加指定前后缀,增加标签灵活度。
List<Employee> queryTrim(@Param("name") String name,@Param("salary") Double salary);
<select id="queryTrim" resultType="com.landy.pojo.Employee">
select emp_name , emp_salary from t_emp
<trim prefix="where" prefixOverrides="and | or" suffixOverrides="and | or">
<if test="name != null">
emp_name = #{name}
</if>
<if test="salary != null and salary > 100">
and emp_salary = #{salary}
</if>
</trim>
</select>
<trim>标签:控制条件部分的两端是否包含某些字符
- prefix属性:指定需要动态添加的前缀。例子中意为动态添加where标签
- suffix属性:指定要动态添加的后缀
- prefixOverrides属性:需要动态删去或忽略的重复前缀内容,用 | 来分隔多个内容。例子中意为忽略SQL语句前多余的and和or
- suffixOverrides属性:需要需要动态删去或忽略的重复后缀内容,用 | 来分隔多个内容。例子中意为忽略SQL语句后多余的and和or
四、choose / when / otherwise标签
类似java中的switch-case语句,在多条分支中,仅执行一个语句。
- 从上到下依次判断<when>是否可执行
- 遇到第一个满足条件的<when>分支标签会被采纳
- 当一个标签被采纳后,其他分支将不再考虑
- 当所有分值都不满足,则执行<otherwise>条件分支
// 如果name非空则使用name进行查询,若果name为空,salary非空则使用salary进行查询,否则全部返回
List<Employee> queryCase(@Param("name") String name,@Param("salary") Double salary);
<select id="queryCase" resultType="com.landy.pojo.Employee">
select emp_name , emp_salary from t_emp
where
<choose>
<when test="name != null">
emp_name = #{name}
</when>
<when test="salary!=null">
emp_salary > #{salary}
</when>
<otherwise>
1=1
</otherwise>
</choose>
</select>
五、foreach标签
对传入的集合对象执行批量操作。
// 根据多个id批量查询
List<Employee> queryBatch(@Param("ids") List<Integer> ids);
// 根据多个id批量删除
int deleteBatch(@Param("ids")List<Integer> ids);
int insertBatch(@Param("emps")List<Employee> employees);
int updateBatch(@Param("emps")List<Employee> employees);
<!--
collection:待遍历的集合
open:遍历之前要追加的字符串
close:遍历结束后要追加的字符串
separator:遍历集合中元素之间的分隔符
item:每个遍历项的名称
-->
<select id="queryBatch" resultType="emp">
select * from t_emp
where emp_id in
<foreach collection="ids" open="(" separator="," close=")" item="id">
#{id}
</foreach>
</select>
<!--
上述标签等于语句:select * from t_emp where emp_id in (1,2,3,4,5)
-->
<delete id="deleteBatch">
delete from t_emp
where emp_id in
<foreach collection="ids" open="(" separator="," close=")" item="id">
#{id}
</foreach>
</delete>
<!--
如果一个语句需要重复多词执行,需要声明多语句
数据连接池配置时携带参数 ...//database?allowMultiQueries=true
-->
<update id="updateBatch">
<foreach collection="emps" separator=";" item="emp">
update t_emp
set emp_name = #{emp.empName},emp_salary = #{emp.empSalary}
where emp_id = #{emp.empId}
</foreach>
</update>
<insert id="insertBatch">
insert into t_emp (emp_name,emp_salary) values
<foreach collection="emps" separator="," item="emp">
(#{emp.empName},#{emp.empSalary})
</foreach>
</insert>
<foreach>标签:包裹需要重复执行的语句模块,可以是整句,也可以是部分。
collection属性:传入的集合参数,需要循环操作的list
open属性:遍历之前追加的字符串,如“(”
seperator属性:遍历集合元素之间的分隔符,如“,”
close属性:遍历之后需要追加的字符串,如“)”
如果完整语句被<foreach>标签包裹,且需要多词被执行,seperator为分号“;”,同时需要在config文件中添加相关配置:
设置参数://database?allowMultiQueries=true
<property name="url" value="jdbc:mysql://localhost:3306/mybatis-example?allowMultiQueries=true"/>
六、SQL片段复用
可以将反复出现、常用的SQL语句抽离出来,需要的时候使用标签引用即可,简化开发。
<sql id="selectSql">
select * from t_emp
</sql>
<select id="queryBatch" resultType="emp">
<include refid="selectSql"></include>
where emp_id in
<foreach collection="ids" open="(" separator="," close=")" item="id">
#{id}
</foreach>
</select>
将需要抽取的SQL语句用<sql>标签包裹,并注明唯一标识id。后续重复使用时使用<include id="myId">引用即可