關於動態SQL使用時的傳參方式
一般情況下映射文件中不寫參數,即省略parameterType項,在傳參時,將參數名和參數值put入Map對象中,傳遞Map類對象。在映射文件中直接#{參數名}使用。
if標籤 :用於無條件查詢或者單條件查詢
可以用與多條件查詢,但是需要把控傳入的參數不會造成SQL語句的錯誤
<if></if>標籤中的test表示if成立的條件,test=“”引號內爲判斷條件,如果成立,直接將if標籤內的SQL拼接在前面的SQL語句之後。
基本格式:
<!-- 通過Map傳參,Map中是否含有name鍵 -->
<if test="name!=null">
where p.name like concat('%',#{name},'%')
</if>
<!--可以使用多個if語句-->
<if test="id!=null">
where p.id = #{id}
</if>
where標籤 用於無條件查詢或者多條件查詢
where標籤的作用:
- 起where關鍵字的作用
- 可以自動去掉SQL語句中不符合SQL語法規則的and、or等連接符
<where></where>標籤和標籤一起使用,其基本格式如下:
當where標籤內的if標籤成立時,會將if標籤內的語句連接在SQL語句的後面,如果if標籤的語句含有無用的and或者or,則自動刪去
<where>
<if test="id!=null">
and p.id=#{id}
</if>
<if test="name!=null">
and p.name like concat("%",#{name},"%")
</if>
</where>
set標籤:用於數據更新時選擇條件更新
set標籤的作用(和where標籤的作用類似,內部使用if標籤):
- 起set關鍵字的作用
- 自動添加逗號
基本格式如下:
<set>
<if test="name != null">name=#{name},</if>
<if test="price != null">price=#{price}</if>
</set>
trim標籤:字符串的處理,包括拼接字符和去除字符,可以從首部或者尾部
prefix:給sql語句拼接的前綴
suffix:給sql語句拼接的後綴
prefixesToOverride: 去除sql語句前面的關鍵字或者字符,該關鍵字或者字符由prefixesToOverride屬性指定,假設該屬性指定爲”AND”,當sql語句的開頭爲”AND”,trim標籤將會去除該”AND”
suffixesToOverride: 去除sql語句後面的關鍵字或者字符,該關鍵字或者字符由suffixesToOverride屬性指定
實現where標籤功能:
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
實現set標籤功能:
<trim prefix="SET" suffixOverrides=",">
...
</trim>
choose標籤:用於選擇條件查詢,或者條件存在互斥
<choose></choose>標籤同樣和<where>標籤一起使用
<choose>標籤作爲<if><\if>標籤的補充,相當於if else的功能,<when></when>標籤相當於if,<otherwise></otherwise>標籤相當於else ,當所有的when條件都不成立時,choose標籤纔會執行;如果有一個成立,choose標籤語句都不會執行。
當有多個<when></when>標籤時,相當於if ,else if, else;只會執行條件最先成立的那一個。choose:選擇,選擇一個標籤執行內的語句執行
基本結構如下:
<where>
<choose>
<when test="price!=null">
price > #{price}
</when>
<when test="name!=null">
p.name like concat("%",#{name},"%")
</when>
<otherwise>
p.id = 6
</otherwise>
</choose>
</where>
foreach標籤:用於多值查詢(in)
foreach標籤就是用於在使用in進行條件查詢時,用於構建in後的內容
foreach標籤內含有如下元素:
collection :collection屬性的值有三個分別是list、array、map三種,分別對應的參數類型爲:List、數組、map集合
item : 表示在迭代過程中每一個元素的別名
index :在list和數組中,index是元素的序號,在map中,index是元素的key,該參數可選。
open :前綴
close :後綴
separator :分隔符,表示迭代時每個元素之間以什麼分隔
關於collection參數的問題:
foreach 迭代對象必須是實現 Iterator 接口或者是Map類型的對象。
- 如果在JAVA代碼中直接傳入List或者數組,直接使用list、array(使用傳入的參數名會報錯);
- 如果傳入的參數爲map類型或者對象類型,參數應該爲屬性值。比如傳入一個Map類型的對象(對象由HashMap類實例化),collection=“key值”,並且要保證key所對應的value值可以使用Iterator進行迭代。如下所示:
List<Integer> paramesList=new ArrayList<>();
paramesList.add(1);
paramesList.add(2);
paramesList.add(3);
int[] paramesArray= {1,2,3};
Map<String,Object> paramesMap=new HashMap<>();
paramesMap.put("value1", 1);
paramesMap.put("value2", paramesList);
paramesMap.put("value3",paramesArray);
// List<Product> ps=session.selectList("selectProductForeach", parames);
// List<Product> ps=session.selectList("selectProductForeach", paramesArray);
List<Product> ps=session.selectList("selectProductForeach", paramesMap);
// List<Product> ps=session.selectList("selectProductForeach", c);
for(Product p:ps)
{
System.out.println(p.getId()+" "+p.getName()+" "+p.getPrice());
}
session.close();
<!-- foreach 標籤的使用 -->
<select id="selectProductForeach" resultType="Product">
select * from product where id in
<foreach collection="value3" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
</select>
使用value3或者value4時,均可以正常執行。使用value1會產生**Error evaluating expression ‘value1’. Return value (1) was not iterable.**錯誤。
如果是使用封裝的對象,對象含有List集合屬性,可以使用如下操作:
/*
public class Category {
private int id;
private String name;
List<Product> products;
}
public class Product {
private int id;
private String name;
private float price;
private Category category;
}
*/
Category c=session.selectOne("selectCategoryByID",1);
List<Product> ps=session.selectList("selectProductForeach", c);
<!-- foreach 標籤的使用 -->
<select id="selectProductForeach" resultType="Product">
select * from product where id in
<foreach collection="products" item="item" index="index" open="(" separator="," close=")">
#{item.id}
</foreach>
</select>
bind標籤:實現一次字符串的拼接,在本地以字符串加減的形式實現,避免了使用數據庫的concat函數
普通模糊查詢和使用bind
<!-- -bind標籤學習 -->
<select id="selectProductByNameNB" resultType="Product">
select * from product where name like concat("%",#{name},"%")
</select>
<select id="selectProductByNameBind" resultType="Product">
<bind name="likename" value="'%'+name+'%'"/>
select * from product where name like #{likename}
</select>
注意value裏字符串拼接的方式,字符使用單引號括起來,變量直接+;但是這樣也產生了一個問題:
java代碼:
/**************bind標籤學習*************/
List<Product> ps=session.selectList("selectProductByNameNB", "product1");
for(Product p:ps)
{
System.out.println(p.getId()+" "+p.getName()+" "+p.getPrice());
}
System.out.println("--------------");
List<Product> ps2=session.selectList("selectProductByNameBind", "product1");
for(Product p:ps2)
{
System.out.println(p.getId()+" "+p.getName()+" "+p.getPrice());
}
運行結果:
查詢時都是傳入直接傳入字符串參數,select標籤中都是省略了parameterType選項,但是普通模糊查詢正確運行,使用bind標籤卻找不到name的值,此處需要使用Map傳值纔可以,如下:
Map<String,Object> param=new HashMap<>();
param.put("name", "product1");
List<Product> ps2=session.selectList("selectProductByNameBind", param);
for(Product p:ps2)
{
System.out.println(p.getId()+" "+p.getName()+" "+p.getPrice());
}