mybatis學習筆記(七)- 動態 SQL
阿新 • • 發佈:2018-12-29
工程目錄
1. 環境配置
1.1 建立 EmployeeMapperDynamicSQL 介面
1.2 建立 EmployeeMapperDynamicSQL.xml 檔案
2. 重要標籤的使用
2.1 在 EmployeeMapperDynamicSQL 中加入
// 攜帶了哪個欄位查詢條件就帶上這個欄位的值
public List<Employee> getEmpsByConditionIf(Employee employee);
public List<Employee> getEmpsByConditionTrim (Employee employee);
public List<Employee> getEmpsByConditionChoose(Employee employee);
public void updateEmp(Employee employee);
// 查詢員工id'在給定集合中的
public List<Employee> getEmpsByConditionForeach(@Param("ids") List<Integer> ids);
public void addEmps(@Param("emps") List<Employee> emps);
2.2 if_判斷 & OGNL where_查詢條件
<!-- 查詢員工,要求,攜帶了哪個欄位查詢條件就帶上這個欄位的值 -->
<!-- public List<Employee> getEmpsByConditionIf(Employee employee); -->
<select id="getEmpsByConditionIf" resultType="www.xq.mybatis.bean.Employee">
select * from tbl_employee
<!-- where -->
<where>
<!-- test:判斷表示式(OGNL)
OGNL參照PPT或者官方文件。
c:if test
從引數中取值進行判斷
遇見特殊符號應該去寫轉義字元:
&&:
-->
<if test="id!=null">
id=#{id}
</if>
<if test="lastName!=null && lastName!=""">
and last_name like #{lastName}
</if>
<if test="email!=null and email.trim()!=""">
and email=#{email}
</if>
<!-- ognl會進行字串與數字的轉換判斷 "0"==0 -->
<if test="gender==0 or gender==1">
and gender=#{gender}
</if>
</where>
</select>
2.3 trim_自定義字串擷取
<!--public List<Employee> getEmpsByConditionTrim(Employee employee); -->
<select id="getEmpsByConditionTrim" resultType="www.xq.mybatis.bean.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="lastName!=null && lastName!=""">
last_name like #{lastName} and
</if>
<if test="email!=null and email.trim()!=""">
email=#{email} and
</if>
<!-- ognl會進行字串與數字的轉換判斷 "0"==0 -->
<if test="gender==0 or gender==1">
gender=#{gender}
</if>
</trim>
</select>
2.4 choose_分支選擇
<!-- public List<Employee> getEmpsByConditionChoose(Employee employee); -->
<select id="getEmpsByConditionChoose" resultType="www.xq.mybatis.bean.Employee">
select * from tbl_employee
<where>
<!-- 如果帶了id就用id查,如果帶了lastName就用lastName查;只會進入其中一個 -->
<choose>
<when test="id!=null">
id=#{id}
</when>
<when test="lastName!=null">
last_name like #{lastName}
</when>
<when test="email!=null">
email = #{email}
</when>
<otherwise>
gender = 0
</otherwise>
</choose>
</where>
</select>
2.5 set_與if結合的動態更新
<!--public void updateEmp(Employee employee); -->
<update id="updateEmp">
<!-- Set標籤的使用 -->
update tbl_employee
<set>
<if test="lastName!=null">
last_name=#{lastName},
</if>
<if test="email!=null">
email=#{email},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</set>
where id=#{id}
<!--
Trim:更新拼串
update tbl_employee
<trim prefix="set" suffixOverrides=",">
<if test="lastName!=null">
last_name=#{lastName},
</if>
<if test="email!=null">
email=#{email},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</trim>
where id=#{id} -->
</update>
2.6. foreach_遍歷集合
<!--public List<Employee> getEmpsByConditionForeach(List<Integer> ids); -->
<select id="getEmpsByConditionForeach" resultType="www.xq.mybatis.bean.Employee">
select * from tbl_employee
<!--
collection:指定要遍歷的集合:
list型別的引數會特殊處理封裝在map中,map的key就叫list
item:將當前遍歷出的元素賦值給指定的變數
separator:每個元素之間的分隔符
open:遍歷出所有結果拼接一個開始的字元
close:遍歷出所有結果拼接一個結束的字元
index:索引。遍歷list的時候是index就是索引,item就是當前值
遍歷map的時候index表示的就是map的key,item就是map的值
#{變數名}就能取出變數的值也就是當前遍歷出的元素
-->
<foreach collection="ids" item="item_id" separator=","
open="where id in(" close=")">
#{item_id}
</foreach>
</select>
2.7 測試
@Test
public void testDynamicSql() throws IOException{
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try{
EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);
//select * from tbl_employee where id=? and last_name like ?
//測試if\where
Employee employee = new Employee(1, "Admin", null, null);
/* List<Employee> emps = mapper.getEmpsByConditionIf(employee );
for (Employee emp : emps) {
System.out.println(emp);
}*/
//查詢的時候如果某些條件沒帶可能sql拼裝會有問題
//1、給where後面加上1=1,以後的條件都and xxx.
//2、mybatis使用where標籤來將所有的查詢條件包括在內。mybatis就會將where標籤中拼裝的sql,多出來的and或者or去掉
//where只會去掉第一個多出來的and或者or。
//測試Trim
/*List<Employee> emps2 = mapper.getEmpsByConditionTrim(employee);
for (Employee emp : emps2) {
System.out.println(emp);
}*/
//測試choose
/*List<Employee> list = mapper.getEmpsByConditionChoose(employee);
for (Employee emp : list) {
System.out.println(emp);
}*/
//測試set標籤
/*mapper.updateEmp(employee);
openSession.commit();*/
//測試 foreach
List<Employee> list = mapper.getEmpsByConditionForeach(Arrays.asList(1,2));
for (Employee emp : list) {
System.out.println(emp);
}
}finally{
openSession.close();
}
}
3. 標籤的應用
3.1 批量儲存
3.1.1. Employee 類設計
package www.xq.mybatis.bean;
import org.apache.ibatis.type.Alias;
@Alias("emp")
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
private Department dept;
public Employee() {
super();
}
public Employee(Integer id, String lastName, String email, String gender, Department dept) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.dept = dept;
}
public Employee(Integer id, String lastName, String email, String gender) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Employee [id=" + id + ", lastName=" + lastName + ", email="
+ email + ", gender=" + gender + "]";
}
}
3.1.2. Department 類設計
package www.xq.mybatis.bean;
import java.util.List;
public class Department {
private Integer id;
private String departmentName;
private List<Employee> emps;
public Department(Integer id) {
super();
this.id = id;
}
public List<Employee> getEmps() {
return emps;
}
public void setEmps(List<Employee> emps) {
this.emps = emps;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
@Override
public String toString() {
return "Department [id=" + id + ", departmentName=" + departmentName
+ "]";
}
}
3.1.3. EmployeeMapperDynamicSQL 介面設計
public void addEmps(@Param("emps") List<Employee> emps);
3.1.4. EmployeeMapperDynamicSQL.xml 設計
<!-- 批量儲存 -->
<!--public void addEmps(@Param("emps")List<Employee> emps); -->
<!--MySQL下批量儲存:可以foreach遍歷 mysql支援values(),(),()語法-->
<insert id="addEmps">
insert into tbl_employee(
last_name,email,gender,d_id
)
values
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
</foreach>
</insert>
<!-- 這種方式需要資料庫連線屬性allowMultiQueries=true;
這種分號分隔多個sql可以用於其他的批量操作(刪除,修改) -->
<!-- <insert id="addEmps">
<foreach collection="emps" item="emp" separator=";">
insert into tbl_employee(last_name,email,gender,d_id)
values(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
</foreach>
</insert> -->
3.1.5. 測試
@Test
public void testBatchSave() throws IOException{
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try{
EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);
List<Employee> emps = new ArrayList<>();
emps.add(new Employee(null, "smith0x1", "[email protected]", "1",new Department(1)));
emps.add(new Employee(null, "allen0x1", "[email protected]", "0",new Department(1)));
mapper.addEmps(emps);
openSession.commit();
}finally{
openSession.close();
}
}
3.2 內建引數_parameter&_databaseId & bind_繫結
3.2.1. 簡介
- 兩個內建引數:
-
不只是方法傳遞過來的引數可以被用來判斷,取值。。。
-
mybatis預設還有兩個內建引數:
- _parameter:代表整個引數
- 單個引數:_parameter就是這個引數
- 多個引數:引數會被封裝為一個map;_parameter就是代表這個map
- _parameter:代表整個引數
-
_databaseId:如果配置了databaseIdProvider標籤。
- _databaseId就是代表當前資料庫的別名oracle
-
3.2.2. 例項
<!--public List<Employee> getEmpsTestInnerParameter(Employee employee); -->
<select id="getEmpsTestInnerParameter" resultType="www.xq.mybatis.bean.Employee">
<!-- bind:可以將OGNL表示式的值繫結到一個變數中,方便後來引用這個變數的值 -->
<bind name="_lastName" value="'%'+lastName+'%'"/>
<if test="_databaseId=='mysql'">
select * from tbl_employee
<if test="_parameter!=null">
where last_name like #{lastName}
</if>
</if>
<if test="_databaseId=='oracle'">
select * from employees
<if test="_parameter!=null">
where last_name like #{_parameter.lastName}
</if>
</if>
</select>
3.3 抽取可重用的sql片段
3.3.1. 簡介
- sql抽取:經常將要查詢的列名,或者插入用的列名抽取出來方便引用
- include來引用已經抽取的sql:
- include還可以自定義一些property,sql標籤內部就能使用自定義的屬性
- include-property:取值的正確方式${prop},
- #{不能使用這種方式}
3.3.2. 例項
<sql id="insertColumn">
<if test="_databaseId=='oracle'">
employee_id,last_name,email
</if>
<if test="_databaseId=='mysql'">
last_name,email,gender,d_id
</if>
</sql>
<insert id="addEmps">
insert into tbl_employee(
<include refid="insertColumn"></include>
)
values
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
</foreach>
</insert>