1. 程式人生 > >MyBatis之動態sql詳細分類說明

MyBatis之動態sql詳細分類說明

本文主要內容:

  • 1、if_判斷&OGNL
  • 2、where_查詢條件
  • 3、trim_自定義字串擷取,用來處理if連線的問題
  • 4、choose_分支選擇
  • 5、set_與if結合的動態更新
  • 6、foreach
  •      6.1  遍歷集合
  •      6.2  mysql下foreach批量插入的兩種方式
  •      6.3  oracle下批量插入的兩種方式
  •      6.4  oracle下foreach批量儲存兩種方式
  • 7、內建引數_parameter&_databaseId
  • 8、bind_繫結:即在xml中動態的給這個值新增規則
  • 9、sql_抽取可重用的sql片段

1、if_判斷&OGNL

場景:查詢員工,要求,攜帶了哪個欄位查詢條件就帶上這個欄位的值

注意:if中test的寫法,寫and而不是&&,寫or而不是||,或者寫&&,||的轉義字元也可;

          如:&&的轉義字元:&    ""的轉義字元:"

           and最好寫在sql語句的前面,寫<select>標籤中,當id為null時,mybatis會自動去掉第一個and;如果寫後面則不會去掉;

ONGL規則官方文件:http://commons.apache.org/proper/commons-ognl/language-guide.html

轉義字元對應官方文件:http://www.w3school.com.cn/tags/html_ref_entities.html

 <!-- public List<Employee> getEmpsByConditionIf(Employee employee); -->
 <select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.bean.Employee">
 	select * from tbl_employee
 	<!-- where -->
 	<where>
	 	<!-- test:判斷表示式(OGNL),OGNL參照PPT或者官方文件。從引數中取值進行判斷
	 	遇見特殊符號應該去寫轉義字元:
	 	&&:&amp;    "": &quot;   -->
	 	<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、where_查詢條件

 優點:and最好寫在sql語句的前面,寫<select>標籤中,當id為null時,mybatis會自動去掉第一個and;如果寫後面則不會去掉;

 <!-- public List<Employee> getEmpsByConditionIf(Employee employee); -->
 <select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.bean.Employee">
 	select * from tbl_employee
 	<!-- where -->
 	<where>
	 	<!-- test:判斷表示式(OGNL),OGNL參照PPT或者官方文件。從引數中取值進行判斷
	 	遇見特殊符號應該去寫轉義字元:
	 	&&:&amp;    "": &quot;   -->
	 	<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>

3、trim_自定義字串擷取,用來處理if連線的問題

後面多出的and或者or where標籤不能解決 
         prefix="":字首:trim標籤體中是整個字串拼串 後的結果。
                 prefix給拼串後的整個字串加一個字首 
         prefixOverrides="":
                 字首覆蓋: 去掉整個字串前面多餘的字元
         suffix="":字尾
                 suffix給拼串後的整個字串加一個字尾 
         suffixOverrides=""
                 字尾覆蓋:去掉整個字串後面多餘的字元

 <!--public List<Employee> getEmpsByConditionTrim(Employee employee);  -->
 <select id="getEmpsByConditionTrim" resultType="com.atguigu.mybatis.bean.Employee">
 	select * from tbl_employee
 	<!-- 自定義字串的擷取規則 -->
 	<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>

4、choose_分支選擇

相當於Java中的switch-case-break語句;

 <!-- public List<Employee> getEmpsByConditionChoose(Employee employee); -->
 <select id="getEmpsByConditionChoose" resultType="com.atguigu.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>

5、set_與if結合的動態更新

<set>標籤會預設去掉最後一個逗號

<!--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} 
</update> 

<trim>結合set:

<!-- 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}

6、foreach

 6.1  遍歷集合

<foreach>中元素說明:

    collection:指定要遍歷的集合:
        list型別的引數會特殊處理封裝在map中,map的key就叫list
    item:將當前遍歷出的元素賦值給指定的變數
    separator:每個元素之間的分隔符
    open:遍歷出所有結果拼接一個開始的字元
    close:遍歷出所有結果拼接一個結束的字元
    index:索引。遍歷list的時候是index就是索引,item就是當前值
                        遍歷map的時候index表示的就是map的key,item就是map的值

    #{變數名}就能取出變數的值也就是當前遍歷出的元素

<!--public List<Employee> getEmpsByConditionForeach(List<Integer> ids);  -->
<select id="getEmpsByConditionForeach" resultType="com.atguigu.mybatis.bean.Employee">
	select * from tbl_employee
	<foreach collection="ids" item="item_id" separator=","
		open="where id in(" close=")">
		#{item_id}
	</foreach>
</select>

6.2  mysql下foreach批量插入的兩種方式

第一種方式:

MySQL下批量儲存:可以foreach遍歷 ,mysql支援values(),(),()語法

 <!-- 批量儲存 -->
 <!--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>

第二種方式

執行多個insert語句:

<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> 

這種方式需要資料庫連線屬性allowMultiQueries=true;這種分號分隔多個sql可以用於其他的批量操作(刪除,修改)

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?allowMultiQueries=true
jdbc.username=root
jdbc.password=123456

6.3  oracle下批量插入的兩種方式

Oracle資料庫批量儲存: Oracle不支援values(),(),()
Oracle支援的批量方式
1、多個insert放在begin - end裡面
    begin
        insert into employees(employee_id,last_name,email) 
        values(employees_seq.nextval,'test_001','[email protected]');
        insert into employees(employee_id,last_name,email) 
        values(employees_seq.nextval,'test_002','[email protected]');
    end;
2、利用中間表:
    insert into employees(employee_id,last_name,email)
       select employees_seq.nextval,lastName,email from(
              select 'test_a_01' lastName,'test_a_e01' email from dual
              union
              select 'test_a_02' lastName,'test_a_e02' email from dual
              union
              select 'test_a_03' lastName,'test_a_e03' email from dual
       )    
6.4  oracle下foreach批量儲存兩種方式

oracle第一種批量方式:

<foreach collection="emps" item="emp" open="begin" close="end;">
	insert into employees(employee_id,last_name,email) 
	    values(employees_seq.nextval,#{emp.lastName},#{emp.email});
</foreach>

oracle第二種批量方式

insert into employees(
	employee_id,last_name,email
)
		<foreach collection="emps" item="emp" separator="union"
			open="select employees_seq.nextval,lastName,email from("
			close=")">
			select #{emp.lastName} lastName,#{emp.email} email from dual
		</foreach>
</insert>

7、內建引數_parameter&_databaseId

mybatis預設還有兩個內建引數:
         _parameter:代表整個引數
             單個引數:_parameter就是這個引數
             多個引數:引數會被封裝為一個map;_parameter就是代表這個map
         _databaseId:如果配置了databaseIdProvider標籤。
             _databaseId就是代表當前資料庫的別名oracle

注:_databaseId可以在一個方法中來根據不同的資料庫寫不同的sql,方便呼叫

<!--public List<Employee> getEmpsTestInnerParameter(Employee employee);  -->
<select id="getEmpsTestInnerParameter" resultType="com.atguigu.mybatis.bean.Employee">
		<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>

8、bind_繫結:即在xml中動態的給這個值新增規則

bind:可以將OGNL表示式的值繫結到一個變數中,方便後來引用這個變數的值

<!--public List<Employee> getEmpsTestInnerParameter(Employee employee);  -->
<select id="getEmpsTestInnerParameter" resultType="com.atguigu.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>

9、sql_抽取可重用的sql片段

抽取可重用的sql片段。方便後面引用 
          1、sql抽取:經常將要查詢的列名,或者插入用的列名抽取出來方便引用
          2、include來引用已經抽取的sql:
          3、include還可以自定義一些property,sql標籤內部就能使用自定義的屬性
                  include-property:取值的正確方式${prop},
                  #{不能使用這種方式}

<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>

呼叫:

使用<include>標籤進行呼叫,<include refid="insertColumn"></include>

oracle:

insert into employees(
	<!-- 引用外部定義的sql -->
	<include refid="insertColumn">
		<property name="testColomn" value="abc"/>
	</include>
)
		<foreach collection="emps" item="emp" separator="union"
			open="select employees_seq.nextval,lastName,email from("
			close=")">
			select #{emp.lastName} lastName,#{emp.email} email from dual
		</foreach>
</insert>

 mysql:

<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>

也可參考mybatis的jar包中的官方文件檢視以上內容: