1.參考官方文檔
? if:字符判斷
? choose (when, otherwise):分支選擇
? trim (where, set):字符串截取;其中where標簽封裝查詢條件,set標簽封裝修改條件
? foreach
2.if案例
1)在EmployeeMapper接口中添加一個方法:
//攜帶了哪個字段,查詢條件就帶上哪個字段的值
public List<Employee> getEmployeeByConditionIf(Employee employee);
2).如果要寫下列的SQL語句,只要是不為空,就作為查詢條件,如下所示,這樣寫實際上是有問題的,所以我們要寫成動態SQL語句:
<select id="getEmployeeByConditionIf" resultType="com.neuedu.entity.Employee">
select *from tbl_employee where id = #{id} and user_name = #{userName} and email = #{email} and gender = #{gender}
</select>
3)用if標簽改寫為動態SQL,如下所示:
<select id="getEmployeeByConditionIf" resultType="com.neuedu.entity.Employee">
select *from tbl_employee
where
<!--
test:判斷表達式(OGNL)
OGNL參照PPT或者官方文檔。
c:if test
從參數中取值進行判斷
遇見特殊符號,應該去寫轉義字符:參考W3CSchool>>HTML>>ISO8859
-->
<if test="id != null">
id = #{id}
</if>
<if test="userName != null && userName !=''">
and user_name = #{userName}
</if>
<if test="email != null and email.trim() != """>
and email = #{email}
</if>
<!-- ognl會進行字符串和數字的轉換判斷;"0"==0,"1"==1 -->
<if test="gender == 0 or gender == 1">
and gender = #{gender}
</if>
</select>
4).測試代碼:
@Test
public void testGetEmployee(){
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
employee.setId(1);
employee.setUserName("張三豐");
employee.setEmail("sunwukong@163.com");
employee.setGender(1);
List<Employee> list = mapper.getEmployeeByConditionIf(employee);
System.out.println(list);
}
但是仔細來說,上面的sql語句是有問題的,當我們不給動態sql語句傳遞id值的時候,sql語句的拼裝就會有問題!
解決辦法:
1>.給where后面加上1=1,以后的條件都可以使用and xxx了
2>.mybatis可以使用where標簽來將所有的查詢條件包括在內。mybatis就會將where標簽中拼裝的sql,
多出來的and或者or去掉!//需要注意:where標簽只會去掉第一個多出來的and或者or
3.>也就是說使用where標簽有時候還是不能解決問題的,那怎么辦呢?我們這里可以使用trim標簽!
2.trim標簽:可以自定義字符串的截取規則
<select id="getEmployeeByConditionIf" resultType="com.neuedu.entity.Employee">
select *from tbl_employee
<!--
后面多出的and或者or where標簽不能夠解決
prefix="":前綴:trim標簽體重是整個字符串拼串后的結果。
prefix給拼串后的整個字符串加一個前綴
prefixOverrides="":
前綴覆蓋:去掉整個字符串前面多余的字符
suffix="":后綴
suffix給拼串后的整個字符串加一個后綴
suffixOverrides="":
后綴覆蓋:去掉整個字符串后面多余的字符
-->
<trim prefix="where" suffixOverrides="and">
<if test="id != null">
id = #{id} and
</if>
<if test="userName != null && userName !=''">
user_name = #{userName} and
</if>
<if test="email != null and email.trim() != """>
email = #{email} and
</if>
<!-- ognl會進行字符串和數字的轉換判斷;"0"==0,"1"==1 -->
<if test="gender==0 or gender==1">
gender = #{gender}
</if>
</trim>
</select>
3.choose標簽:分支選擇,類似於Java中的帶了break的switch...case
choose (when, otherwise):如果帶了id,就用id查,如果帶了userName就用userName查,只會進入其中一個!
案例演示:
1>.在EmployeeMapper接口中添加一個方法:
public List<Employee> getEmployeeByConditionChoose(Employee employee);
2>.sql映射文件
<!-- public List<Employee> getEmployeeByConditionChoose(Employee employee); -->
<select id="getEmployeeByConditionChoose" resultType="com.neuedu.entity.Employee">
select *from tbl_employee
<where>
<!-- 如果帶了id,就用id查,如果帶了userName就用userName查,只會進入其中一個! -->
<choose>
<when test="id != null">
id = #{id}
</when>
<when test="userName != null">
user_name like #{userName}
</when>
<when test="email != null">
email = #{email}
</when>
<otherwise>
1=1
</otherwise>
</choose>
</where>
</select>
4.trim 中的set標簽(where, set):字符串截取;其中where標簽封裝查詢條件,set標簽封裝修改條件
set元素會動態前置set關鍵字,同時也會消除無關的逗號。
1).在EmployeeMapper中添加一個更新的方法,如下所示:
public void updateEmp(Employee employee);
2)在sql映射文件中,填寫相應的sql語句,如下所示【set標簽可以將字段后面的逗號去掉】:
<update id="updateEmp">
update tbl_employee
<set>
<if test="userName != null">
user_name = #{userName},
</if>
<if test="email != null">
email = #{email},
</if>
<if test="gender != null">
gender = #{gender},
</if>
</set>
where id = #{id}
</update>
測試類代碼為:
@Test
public void testGetEmployee(){
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
employee.setId(1);
employee.setUserName("哈哈");
employee.setEmail("sunwukong@163.com");
employee.setGender(1);
mapper.updateEmp(employee);
}
//當然上面的set標簽我們也可以使用trim標簽來代替,如下所示:
<update id="updateEmp">
update tbl_employee
<trim prefix="set" suffixOverrides=",">
<if test="userName != null">
user_name = #{userName},
</if>
<if test="email != null">
email = #{email},
</if>
<if test="gender != null">
gender = #{gender},
</if>
</trim>
where id = #{id}
</update>
5.foreach:遍歷元素
動態SQL的另一個常用的操作是需要對一個集合進行遍歷,通常在構建in條件語句的時候!
foreach元素允許指定一個集合,聲明集合項和索引變量,並可以指定開閉匹配的字符串以及在迭代之間放置分隔符。
案例演示:
1>.在EmployeeMapper接口中加入一個方法,如下所示:
public List<Employee> getEmpsByConditionForeach(@Param("ids") List<Integer> ids);
2>.在MyBatis的sql映射文件中寫相應的代碼:
<!-- public List<Employee> getEmpsByConditionForeach(List<Integer> ids); -->
<select id="getEmpsByConditionForeach" resultType="com.neuedu.entity.Employee">
select * from tbl_employee where id in
<!--
collection:指定要遍歷的集合
item:將當前遍歷出的元素賦值給指定的變量
separator:每個元素之間的分隔符
open:遍歷出所有記過拼接一個開始的字符
close:遍歷出所有結果拼接一個結束的字符
-->
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</select>
3.>測試類代碼為:
@Test
public void testGetEmployee(){
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
List<Integer> asList = Arrays.asList(1,2,3,4);
List<Employee> emps = mapper.getEmpsByConditionForeach(asList);
for (Employee employee : emps) {
System.out.println(employee);
}
}
foreach標簽還可以用於批量保存數據,如下所示:
1.在EmployeeMapper接口類中添加批量插入的方法:
public void addEmps(@Param("emps") List<Employee> emps);
2.在EmployeeMapper.xml的sql映射文件中添加響應的語句:
<!-- public void addEmps(@Param("emps") List<Employee> emps); -->
<!-- MySQL下批量保存:可以foreach遍歷,mysql支持values(),(),()語法 -->
<insert id="addEmps">
INSERT INTO tbl_employee(user_name,gender,email,d_id) VALUES
<foreach collection="emps" item="emp" separator=",">
(#{emp.userName},#{emp.gender},#{emp.email},#{emp.depart.id})
</foreach>
</insert>
3.測試代碼:
@Test
public void testGetEmployee(){
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
List<Employee> emps = new ArrayList<Employee>();
emps.add(new Employee(0, 1, "allen", "allen@163.com", new Department(1)));
emps.add(new Employee(0, 0, "tom", "tom@163.com", new Department(2)));
emps.add(new Employee(0, 1, "mux", "mux@163.com", new Department(1)));
mapper.addEmps(emps);
}
