動態拼接SQL語句


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);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM