MyBatis动态SQL
2020-05-04 本文已影响0人
JBryan
动态 SQL 是 MyBatis 的强大特性之一。根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
DynamicSQLDemo.java
package com.ljessie.mybatisdemo.dao;
import com.ljessie.mybatisdemo.entity.Student;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface DynamicSQLDemo {
List<Student> getStudentByConditionIf(Student student);
List<Student> getStudentByConditionTrim(Student student);
List<Student> getStudentByConditionChoose(Student student);
void updateStudent(Student student);
void addStudents(@Param("students")List<Student> students);
}
DynamicSQLDemo.xml
<?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.ljessie.mybatisdemo.dao.DynamicSQLDemo">
<!-- 查询Student,要求:携带了哪个字段,就带上哪个字段的值-->
<!-- List<Student> getStudentByConditionIf(Student student);-->
<select id="getStudentByConditionIf" resultType="Student">
select * from student
<!-- 使用where标签,解决多出来的and问题-->
<where>
<!--test:判断表达式(OGNL表达式参照官方文档)
从参数中取值进行判断
有一个问题就是:如果传入的参数中,没有id,后面的第一个条件是and ***,就会出现语法错误-->
<if test="id != 0">
id = #{id}
</if>
<if test="name != null and name != ''">
and name = #{name}
</if>
<!--ONGL会自动转换字符串与数字:例如"0"==0是成立的-->
<if test="age != 0">
and age = #{age}
</if>
</where>
</select>
<!-- List<Student> getStudentByConditionTrim(Student student);-->
<select id="getStudentByConditionTrim" resultType="Student">
select * from student
<!--where标签,没有办法解决and或or在条件后面的情况
prefix="" :前缀,给拼成的字符串加个前缀
prefixOverrides="":前缀覆盖,整个字符串前面多余的串给去掉
suffix="":后缀,给拼成的字符串加个后缀
suffixOverrides="":后缀覆盖,整个字符串后面多余的串给去掉-->
where
<trim suffixOverrides="and">
<if test="id != 0">
id = #{id} and
</if>
<if test="name != null and name != ''">
name = #{name} and
</if>
<!--ONGL会自动转换字符串与数字:例如"0"==0是成立的-->
<if test="age != 0">
age = #{age}
</if>
</trim>
</select>
<!--如果带了id,就用id查,如果带了lastName,就用lastName查。只会进入其中一个-->
<!-- getStudentByConditionChoose-->
<select id="getStudentByConditionChoose" resultType="Student">
select
<include refid="selectColumn"></include>
from student
<where>
<choose>
<when test="id!=0">
id = #{id}
</when>
<when test="name!=null">
name = #{name}
</when>
<otherwise>
1 = 1
</otherwise>
</choose>
</where>
</select>
<!-- 场景:带了哪一列的值,就更新哪一列-->
<!--set封装修改条件-->
<!-- updateStudent-->
<update id="updateStudent" >
update student
<set>
<if test="name != null">
name = #{name}
</if>
<if test="age != 0">
age = #{age}
</if>
</set>
<where>
id = #{id}
</where>
</update>
<!--批量保存-->
<!-- addStudents-->
<!-- MySQL支持insert into student () values (),(),()这种语法,可以用这一种方式-->
<insert id="addStudents">
insert into student (name,age,department_id)
values
<foreach collection="students" item="student" separator=",">
(#{student.name},#{student.age},#{student.department.id})
</foreach>
</insert>
<!-- 其他数据库用这种方式-->
<!-- <insert id="addStudents">-->
<!-- <foreach collection="students" item="student" separator=";">-->
<!-- insert into student (name,age,department_id)-->
<!-- values (#{student.name},#{student.age},#{student.department.id})-->
<!-- </foreach>-->
<!-- </insert>-->
<!-- 两个内置参数:
不只是方法传递过来的参数可以用来判断,取值。
MyBatis默认还有两个内置的参数:
_parameter:代表整个参数。
方法传来单个参数:_parameter就是这个参数。
方法传来多个参数:参数会被封装为一个map;_parameter就是这个map
_databaseId:如果配置了databaseIdProvider标签,_databaseId就是代表当前数据库的别名
-->
<!--sql标签:抽取可重用的sql片段,方便后面引用
1、经常将要查询的列名,或者插入用的列名抽取出来,方便引用
2、include标签来引用已经抽取的sql片段-->
<sql id="selectColumn">
id,name,age,department_id
</sql>
</mapper>