共計 6986 個字符,預計需要花費 18 分鐘才能閱讀完成。
這篇“MySQL 動態 SQL 拼接怎么實現”文章的知識點大部分人都不太理解,所以丸趣 TV 小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“MySQL 動態 SQL 拼接怎么實現”文章吧。
一、動態 sql 拼接目標
能夠使用 mybatis 的標簽實現動態 SQL 拼接
分析
我們在前邊的學習過程中,使用的 SQL 語句都非常簡單。而在實際業務開發中,我們的 SQL 語句通常是動態拼接而成的,比如:條件搜索功能的 SQL 語句。
# 提供了一個功能:用戶可以在頁面上根據 username、sex、address 進行搜索
# 用戶輸入的搜索條件:可以是一個條件,也可能是兩個、三個
# 只輸入一個條件:姓名是 王
SELECT * FROM USER WHERE username LIKE % 王 %
# 只輸入一個條件:性別是“男”SELECT * FROM USER WHERE sex = 男
# 輸入兩個條件:姓名“王”,性別“男”SELECT * FROM USER WHERE username LIKE % 王 % AND sex = 男
# 輸入三個條件:姓名“王”,性別“男”,地址“北京”SELECT * FROM USER WHERE username LIKE % 王 % AND sex = 男 AND address LIKE % 北京 %
在 Mybatis 中,SQL 語句是寫在映射配置的 XML 文件中的。Mybatis 提供了一些 XML 的標簽,用來實現動態 SQL 的拼接。
常用的標簽有:
if /if:用來進行判斷,相當于 Java 里的 if 判斷
where /where:通常和 if 配合,用來代替 SQL 語句中的 where 1=1
foreach /foreach:用來遍歷一個集合,把集合里的內容拼接到 SQL 語句中。例如拼接:in (value1, value2, …)
sql /sql:用于定義 sql 片段,達到重復使用的目的
講解 1. 準備 Mybatis 環境
創建 java 項目,導入 jar 包;準備 JavaBean
創建映射器接口 UserDao
創建映射配置文件 UserDao.xml
創建全局配置文件 SqlMapConfig.xml
創建日志配置文件 log4j.properties
2. if 標簽:語法介紹
if test= 判斷條件,使用 OGNL 表達式進行判斷
SQL 語句內容, 如果判斷為 true,這里的 SQL 語句就會進行拼接 /if
使用示例
根據用戶的名稱和性別搜索用戶信息。把搜索條件放到 User 對象里,傳遞給 SQL 語句
映射器接口 UserDao 上加方法
package com.demo.dao;import com.demo.domain.User;import java.util.List;public interface UserDao {
/**
* 根據 username 和 sex 搜索用戶
* @param user 封裝了搜索條件的 User 對象
* @return 搜索的結果
*/
List User search2(User user);}
映射文件 UserDao.xml 里配置 statement
?xml version= 1.0 encoding= UTF-8 ? !DOCTYPE mapper
PUBLIC -//mybatis.org//DTD Mapper 3.0//EN
http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespace= com.itheima.dao.UserDao
!--
if 標簽:用于條件判斷
語法:if test= 用 OGNL 表達式判斷 如果判斷為 true,這里的內容會拼接上去 /if
注意:標簽里寫 OGNL 表達式,不要再加 #{}、${}
常用的 OGNL 表達式: 比較:, , =, =, ==, != 或者 gt, lt, gte, lte, eq, neq
邏輯:,||,! 或者 and, or, not
調用方法:username.length(), list.size()
--
select id= search2 resultType= User
select * from user where 1=1 if test= username != null and username.length() 0
and username like % #{username} % /if
if test= sex != null and sex.length() 0
and sex = #{sex} /if
/select /mapper
功能測試,在測試類里加測試方法
package com.demo;import com.demo.dao.UserDao;import com.demo.domain.User;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.After;import org.junit.Before;import org.junit.Test;import java.io.IOException;import java.io.InputStream;import java.util.List;public class SqlTest {
private UserDao userDao;
private SqlSession session;
private InputStream is;
/**
* 要求:根據 username 和 sex 搜索用戶
* 搜索條件放到 user 對象里
*/
@Test
public void testSearch(){ User user = new User();
// user.setUsername( 王
// user.setSex( 男
List User userList = userDao.search2(user);
userList.forEach(System.out::println);
}
public void init() throws IOException {
//1. 讀取全局配置文件
is = Resources.getResourceAsStream( SqlMapConfig.xml
//2. 得到一個 SqlSession 對象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
session = factory.openSession();
userDao = session.getMapper(UserDao.class);
}
@After
public void destroy() throws IOException { session.close();
is.close();
}}
3. where 標簽語法介紹
在剛剛的練習的 SQL 語句中,我們寫了 where 1=1。如果不寫的話,SQL 語句會出現語法錯誤。Mybatis 提供了一種代替 where 1= 1 的技術:where /where 標簽。
代碼示例
把上一章節的實現代碼進行優化,使用 where /where 標簽代替 where 1=1
映射器 UserDao 的 search2 方法:已有,不用修改
/**
* 根據 username 和 sex 搜索用戶
* @param user 封裝了搜索條件的 User 對象
* @return 搜索的結果
*/List User search2(User user);
在映射文件 UserDao.xml 里修改 SQL 語句
!--
where 標簽:讓 Mybatis 幫我們生成一個 where 關鍵字
Mybatis 會智能判斷: 如果一個條件都沒有,就不生成 where 關鍵字
如果有條件,會判斷是否有多余的 and 關鍵字,把多余的 and 去掉
注意:建議把所有的 where 條件都放到 where 標簽里邊
-- select id= search2 resultType= User
select * from user where
if test= username != null and username.length() 0
and username like % #{username} % /if
if test= sex != null and sex.length() 0
and sex = #{sex} /if
/where /select
在測試類里進行功能測試:測試方法不需要修改
@Testpublic void testSearch(){ User user = new User();
// user.setUsername( 王
// user.setSex( 男
List User userList = userDao.search2(user);
userList.forEach(System.out::println);}
4. foreach 標簽語法介紹
foreach 標簽,通常用于循環遍歷一個集合,把集合的內容拼接到 SQL 語句中。例如,我們要根據多個 id 查詢用戶信息,SQL 語句:
select * from user where id = 1 or id = 2 or id = 3;select * from user where id in (1, 2, 3);
假如我們傳參了 id 的集合,那么在映射文件中,如何遍歷集合拼接 SQL 語句呢?可以使用 foreach 標簽實現。
!--
foreach 標簽:collection:被循環遍歷的對象,使用 OGNL 表達式獲取,注意不要加 #{}
open:循環之前,拼接的 SQL 語句的開始部分
item:定義變量名,代表被循環遍歷中每個元素,生成的變量名
separator:分隔符
close:循環之后,拼接 SQL 語句的結束部分
標簽體:使用 #{OGNL} 表達式,獲取到被循環遍歷對象中的每個元素
-- foreach collection= open= id in( item= id separator= , close=)
#{id} /foreach
使用示例
有搜索條件類 QueryVO 如下:
package com.itheima.domain;public class QueryVO { private Integer[] ids;
public Integer[] getIds() {
return ids;
}
public void setIds(Integer[] ids) {
this.ids = ids;
}}
在映射器 UserDao 里加方法
/**
* QueryVO 里有一個 Integer[] ids
* 要求:根據 ids 查詢對應的用戶列表
*/List User search3(QueryVO vo);
在映射文件 UserDao.xml 里配置 statement
!--
foreach 標簽:用于循環遍歷
collection:被循環的集合 / 數組
item:定義一個變量
separator:定義拼接時的分隔符
open:拼接字符串時的開始部分
close:拼接字符串時的結束部分
相當于 for(Integer id: ids){}
select * from user where id in(41, 42, 45)
--
select id= search3 resultType= User
!--select * from user where id in(41, 42, 45)--
select * from user where foreach collection= ids open= id in( item= id separator= , close=)
#{id} /foreach
/select
功能測試
@Test
public void testSearch3(){ QueryVO vo = new QueryVO();
vo.setIds(new Integer[]{41,42,43,44,45});
List User userList = userDao.search3(vo);
userList.forEach(System.out::println);
}
5. sql 標簽
在映射文件中,我們發現有很多 SQL 片段是重復的,比如:select * from user。Mybatis 提供了一個 sql 標簽,把重復的 SQL 片段抽取出來,可以重復使用。
語法介紹
在映射文件中定義 SQL 片段:
sql id= 唯一標識 sql 語句片段 /sql
在映射文件中引用 SQL 片段:
include refid= sql 片段的 id /include
使用示例
在查詢用戶的 SQL 中,需要重復編寫:select * from user。把這部分 SQL 提取成 SQL 片段以重復使用
要求:QueryVO 里有 ids,user 對象。根據條件進行搜索
修改 QueryVO,增加成員變量 user
package com.itheima.domain;/**
* @author liuyp
* @date 2021/09/07
*/public class QueryVO { private Integer[] ids;
private User user;
//get/set 方法……}
在映射器 UserDao 里加方法
/**
* 動態 SQL 拼接的綜合應用:if、where、foreach
* 要求:QueryVo 里有 ids、username、sex 值,根據這些值進行搜索
*/
List User search4(QueryVO vo);
在映射文件 UserDao.xml 里配置 statement
select id= search4 resultType= User
!--select * from user--
include refid= selUser /
where
if test= ids != null and ids.length 0
foreach collection= ids open= and id in( item= id separator= , close=)
#{id} /foreach
/if
!-- if test= user != null
if test= user.username != null and user.username.length() 0
and username like % #{user.username} %
/if
if test= user.sex != null and user.sex.length() 0
and sex = #{user.sex}
/if
/if --
include refid= userCondition /
/where /select !--
sql 標簽:用于定義一個 sql 片段
include 標簽:什么時候要引用某個 SQL 片段,就使用 include 標簽
注意:引入 SQL 片段之后,最終的 SQL 語句必須要完全符合語法
-- sql id= selUser select * from user /sql sql id= userCondition
if test= user != null
if test= user.username != null and user.username.length() 0
and username like % #{user.username} % /if
if test= user.sex != null and user.sex.length() 0
and sex = #{user.sex} /if
/if /sql
在測試類里加測試方法
@Test
public void testSearch4(){ QueryVO vo = new QueryVO();
vo.setIds(new Integer[]{41,42,43,44,45});
// User user = new User();
// user.setUsername( 王
// user.setSex( 男
// vo.setUser(user);
List User userList = userDao.search4(vo);
userList.forEach(System.out::println);
}
以上就是關于“MySQL 動態 SQL 拼接怎么實現”這篇文章的內容,相信大家都有了一定的了解,希望丸趣 TV 小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注丸趣 TV 行業資訊頻道。