實現動態SQL的四種方式: 1、XML配置 使用XML配置動態SQL,細節不表,詳參:《MyBatis快速上手與知識點總結》 - 5.4 多條件查詢 - 動態查詢 2、腳本SQL 使用註解實現,將XML文件的內容轉換為註釋即可 當然,這種方式可讀性差,且難以維護 @Select("<script>s ...
目錄
實現動態SQL的四種方式:
1、XML配置
使用XML配置動態SQL,細節不表,詳參:《MyBatis快速上手與知識點總結》 - 5.4 多條件查詢 - 動態查詢
2、腳本SQL
- 使用註解實現,將XML文件的內容轉換為註釋即可
- 當然,這種方式可讀性差,且難以維護
@Select("<script>select * from user <if test=\"id !=null \">where id = #{id} </if></script>")
public List<User> findUserById(User user);
3、在方法中構建SQL
- Dao層介面不寫實現,次數使用內部類來生成動態SQL,並傳入 @SelectProvider 註釋
- 增改刪也有對應的 @InsertProvider、@UpdateProvider、@DeleteProvider 註釋
- 相比於腳本SQL更加清晰,比較直觀,但是如果SQL過長的話,拼接會非常麻煩
@Mapper
public interface MybatisDao {
//使用UserDaoProvider類的findUserById方法來生成sql
@SelectProvider(type = UserDaoProvider.class, method = "findUserById")
public List<User> findUserById(User user);
class UserDaoProvider {
public String findUserById(User user) {
String sql = "SELECT * FROM user";
if(user.getId()!=null){
sql += " where id = #{id}";
}
return sql;
}
}
}
4、結構化SQL
- 這是把前面的內部類改造一下:
- SELECT:表示要查詢的欄位,如果一行寫不完,可以在第二行再寫一個SELECT,這兩個SELECT會智能的進行合併而不會重覆
- FROM 和 WHERE:跟SELECT一樣,可以寫多個參數,也可以在多行重覆使用,最終會智能合併而不會報錯。
- 這樣語句適用於寫很長的SQL時,能夠保證SQL結構清楚。便於維護,可讀性高。
- 但是這種自動生成的SQL和HIBERNATE一樣,在實現一些複雜語句的SQL時會束手無策。所以需要根據現實場景,來考慮使用哪一種動態SQL
- 上面的例子只是最基本的用法:更多詳細用法,可以參考mybatis中文網的專門介紹:
http://www.mybatis.org/mybatis-3/zh/statement-builders.html
@Mapper
public interface MybatisDao {
//使用UserDaoProvider類的findUserById方法來生成sql
@SelectProvider(type = UserDaoProvider.class, method = "findUserById")
public List<User> findUserById(User user);
public String findUserById(User user) {
return new SQL(){{
SELECT("id,name");
SELECT("other");
FROM("user");
if(user.getId()!=null){
WHERE("id = #{id}");
}
if(user.getName()!=null){
WHERE("name = #{name}");
}
//從這個toString可以看出,其內部使用高效的StringBuilder實現SQL拼接
}}.toString();
}
}
關於動態SQL的List傳值錯誤問題
動態SQL中,有時要對批量數據進行處理,難免會使用list做為參數
1、錯誤代碼
- 這是一個最簡單的list傳參,但是在運行時會報傳參錯誤。
- 這是mybatis內部機製造成的,其參數需要是key/value結構,當遇到這裡不是 key/value結構的list時,mybatis會自己把它轉換成key/value結構,key就是他的名字"list",value就是他的值 list 對象
@SelectProvider(type = UserDaoProvider.class, method = "find")
public List<Map> find(List list);
class UserDaoProvider {
public String find(List list) {
}
}
2、解決錯誤
要正確傳參需要使用key/value結構的map,如下:
@SelectProvider(type = UserDaoProvider.class, method = "find")
public List<Map> find(List list);
class UserDaoProvider {
public String find(Map map) {
List list = (List) map.get("list");
}
}