1. 程式人生 > >mybatis學習筆記(七)- 動態 SQL

mybatis學習筆記(七)- 動態 SQL

工程目錄

image

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 &amp;&amp; lastName!=&quot;&quot;"> and last_name like #{lastName} </if> <if test="email!=null and email.trim()!=&quot;&quot;"> 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 &amp;&amp; lastName!=&quot;&quot;">
		 		last_name like #{lastName} and
		 	</if>
		 	<if test="email!=null and email.trim()!=&quot;&quot;">
		 		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
    • _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. 簡介

  1. sql抽取:經常將要查詢的列名,或者插入用的列名抽取出來方便引用
  2. include來引用已經抽取的sql:
  3. 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>