※動態SQL
有個要注意的地方要判斷大小用"<"和">",但"<"在XML有特殊的意義,它會以為是標籤,如<h1><head><configuration>…等,有兩種方式可解決
一.CDATA
<![CDATA[程式碼…
]]>
這種方式是包起來的部分不會對它做認何的轉譯之類的
二.實體參照
如 就是空格,"就是",這裡有較詳細的表可參考----------------------------------------------------------------------------------------------------------
以下的標籤都是用這個且標籤一定要是小寫
<select id="testDynamicSQL" parameterType="Chess" resultMap="ChessInterface" >
</select>
測試類如下:
System.out.println("----------Chess.testDynamicSQL----------");
Chess chess = new Chess();
// chess.setChessNo(12);
// chess.setPrice(50);
List<Chess> listChess = sqlSession.selectList("Chess.testDynamicSQL", chess);
for(Chess c:listChess){
System.out.println("chessNo=" + c.getChessNo());
System.out.println("name=" + c.getName());
System.out.println("price=" + c.getPrice());
System.out.println("productDate=" + c.getProductDate());
System.out.println("---------------------------------");
}
※<if>和<choose><when><otherwise>
以java的角度看if就是if沒有else;
choose裡面包when和otherwise,when就是if,otherwise就是else
SELECT
<include refid="column" />
FROM CHESS
WHERE 1=1
<if test="chessNo != null">
AND CHESS_NO = #{chessNo}
</if>
<if test="name != null">
AND NAME = #{name}
</if>
<if test="price < 30">
AND PRICE = #{price}
</if>
<if test="productDate != null">
AND PRODUCT_DATE = #{productDate}
</if>
ORDER BY PRICE
SELECT
<include refid="column" />
FROM CHESS
WHERE 1=1
<choose>
<when test="chessNo != null">
AND CHESS_NO = #{chessNo}
</when>
<when test="name != null">
AND NAME = #{name}
</when>
<otherwise>
AND PRICE = #{price}
</otherwise>
</choose>
ORDER BY PRICE
※<where>和<trim>和<set>
上個例子的WHERE 1=1看起來看怪,所以mybatis提供一個自動幫我們判斷需不需要WHERE,也能智慧的去掉AND、OR的功能,以上面的例子就可以這樣寫:SELECT
<include refid="column" />
FROM CHESS
<WHERE>
<if test="chessNo != null">
AND CHESS_NO = #{chessNo}
</if>
<if test="name != null">
AND NAME = #{name}
</if>
<if test="price < 30">
AND PRICE = #{price}
</if>
<if test="productDate != null">
AND PRODUCT_DATE = #{productDate}
</if>
</WHERE>
ORDER BY PRICE
SELECT
<include refid="column" />
FROM CHESS
<WHERE>
<choose>
<when test="chessNo != null">
AND CHESS_NO = #{chessNo}
</when>
<when test="name != null">
AND NAME = #{name}
</when>
<otherwise>
AND PRICE = #{price}
</otherwise>
</choose>
</WHERE>
ORDER BY PRICE
如果有特殊須求可以用<trim>
SELECT
<include refid="column" />
FROM CHESS
<trim prefix="WHERE" prefixOverrides="ORDER BY PRICE|AND|OR">
<choose>
<when test="chessNo != null">
AND CHESS_NO = #{chessNo}
</when>
<when test="name != null">
AND NAME = #{name}
</when>
<otherwise>
ORDER BY PRICE 1=1
</otherwise>
</choose>
</trim>
prefix就是在最前面增加什麼;prefixOverrides就是將最前面的什麼取代成空,有順序問題,最前面找到了,就先取代
還有suffix和suffixOverrides就是在最後面增加什麼,和將最後面的什麼取代成空
而set是配合update的,如下:
<update id="update" parameterType="Chess">
UPDATE CHESS
<set>
<if test="chessNo != null">
NAME = #{name},
</if>
<if test="price != null">
PRICE = #{price},
</if>
</set>
<where>
CHESS_NO = #{chessNo}
</where>
</update>
會幫我們判斷最後面的逗點,會把他變不見所以<where>就等於
<trim prefix="WHERE" prefixOverrides="AND |OR "></trim>
而<set>就等於
<trim prefix="SET" suffixOverrides=","></trim>
所以<where>和<set>,其實就是<trim>分出來的,可能因為常用的關係
<bind>
Dept d = new Dept();
d.setdName("O");
List<Dept> bind1 = mapper.getDeptsByDeptUseBind(d);
bind1.stream().forEach(x -> {
System.out.println(x.getdName());
});
Map<String, String> map = new HashMap<>();
map.put("kkk", "O");
List<Dept> bind2 = mapper.getDeptsByMapUseBind(map);
bind2.stream().forEach(x -> {
System.out.println(x.getdName());
});
※參數給 java bean 或 Map 都可以
<select id="getDeptsByDeptUseBind" resultType="mp.bean.Dept" parameterType="mp.bean.Dept">
<!-- <bind name="xxx" value="'%' + dName + '%'"/> -->
<bind name="xxx" value="'%' + _parameter.getdName() + '%'" />
select * from dept
where dname like #{xxx}
</select>
<select id="getDeptsByMapUseBind" resultType="mp.bean.Dept" parameterType="mp.bean.Dept">
<!-- <bind name="xxx" value="'%' + kkk + '%'"/> -->
<bind name="xxx" value="'%' + _parameter.kkk + '%'" />
select * from dept
where dname like #{xxx}
</select>
※ _parameter 是內鍵的
※這兩種方式都有兩種用法,其中 dName 是 java bean 的名稱
※用 Map 時,_parameter 必須要.key 的名稱
※<foreach>
主要是給IN使用的,如下:SELECT
<include refid="column" />
FROM CHESS
<where>
PRICE IN
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</where>
.item為foreach裡要使用的變數名稱.index索引,我沒加也ok,可能預設會幫我們加,會自動從0開始
.collection有 list、array、Map 的 key 名稱、@Param 裡的名稱,Set 一樣給 list
※1.但 list、array 如果使用 @Param,變數就只能是 @Param的名稱或 param1,統一用@Param ,XML 就不用改了
2.Map 如果使用 @Param,變數就只能是 @Param的名稱.key名稱或 param1.key名稱
.open開始時用什麼符號開始,IN當然是「(」
.close結束時用什麼符號結束,IN當然是「)」
.separator分開始用什麼符號,IN當然是「,」,如果寫在foreach裡,最後會多一個,,所以這個功能會幫我們判斷並刪除
測試類:
List<Integer> l = new ArrayList<>();
l.add(30);
l.add(40);
l.add(50);
List<Chess> listChess = sqlSession.selectList("Chess.testDynamicSQL", l);
for(Chess c:listChess){
System.out.println("chessNo=" + c.getChessNo());
System.out.println("name=" + c.getName());
System.out.println("price=" + c.getPrice());
System.out.println("productDate=" + c.getProductDate());
System.out.println("---------------------------------");
}
如果collection想給array,就改第二個參數就可以了
List<Chess> listChess = sqlSession.selectList("Chess.testDynamicSQL", new Integer[]{30,40,50});
如果collection和你傳的參數不匹配, 就會出Parameter 'list' not found.的錯,''裡面是你在collection裡打的字還可以放map:
List<Integer> l = new ArrayList<>();
l.add(30);
l.add(40);
l.add(50);
Map<String, List<Integer>> map = new HashMap<>();
map.put("xxx", l);
List<Chess> listChess = sqlSession.selectList("Chess.testDynamicSQL", map);
for(Chess c:listChess){
System.out.println("chessNo=" + c.getChessNo());
System.out.println("name=" + c.getName());
System.out.println("price=" + c.getPrice());
System.out.println("productDate=" + c.getProductDate());
System.out.println("---------------------------------");
}
記得collection也要給map的變數xxx,不然會出The expression 'list' evaluated to a null value.的錯
※證明index從0開始
我的資料庫有如下資料:List重點是從0~9跑了10次迴圈,裡面放什麼不重要
List<Integer> l = new ArrayList<>();
for(int i=0; i<10; i++){
l.add(30);
}
List<Chess> listChess = sqlSession.selectList("Chess.testDynamicSQL", l);
for(Chess c:listChess){
System.out.println("chessNo=" + c.getChessNo());
System.out.println("name=" + c.getName());
System.out.println("price=" + c.getPrice());
System.out.println("productDate=" + c.getProductDate());
System.out.println("---------------------------------");
}
因為要用到index, 我給ooo,不打不行,我想說預設值應該是index,結果也不行,反正要用到就打就對了
SELECT
<include refid="column" />
FROM CHESS
<where>
CHESS_NO IN
<foreach item="item" index="ooo" collection="list" open="(" separator="," close=")">
#{ooo}
</foreach>
</where>
結果:
----------Chess.testDynamicSQL----------
chessNo=7
name=象棋
price=50
productDate=Sat Jul 18 16:01:37 CST 2015
---------------------------------
chessNo=8
name=西洋棋
price=120
productDate=Sat Jul 18 16:02:20 CST 2015
---------------------------------
chessNo=9
name=跳棋
price=30
productDate=Sat Jul 18 16:03:10 CST 2015
---------------------------------
chessNo我的資料庫有10的沒顯示出來,我的迴圈跑10次,那就表示它一定是從0開始跑,跑到9,所以9有跑出來
index本身是數字,所以裡面還可以運算,我有在裡面加1試試,還真的10就跑出來了
※大量增刪改
Oracle:
Emp e1 = new Emp();
e1.setEname("ccc");
e1.setDeptno(20);
Emp e2 = new Emp();
e2.setEname("ddd");
e2.setDeptno(30);
List<Emp> list = new ArrayList<>();
list.add(e1);
list.add(e2);
mapper.bigInsert1(list);
//mapper.bigInsert2(list);
//mapper.bigUpdate(Arrays.asList("xxx", "ooo"));
//mapper.bigDelete(Arrays.asList("xxx", "ooo"));
mapper.getEmp().stream().forEach(x -> {
System.out.println(x.getEname());
});
※
public void bigInsert1(@Param("emp") List<Emp> list);
public void bigInsert2(@Param("emp") List<Emp> list);
public void bigUpdate(List<String> list);
public void bigDelete(List<String> list);
※
<insert id="bigInsert1">
<foreach collection="emp" open="begin" close="end;" item="e">
insert into emp(empno, ename, job, mgr, hiredate, sal, comm, deptno)
values(emp_seq.nextval, #{e.ename}, #{e.job}, #{e.mgr}, #{e.hiredate}, #{e.sal}, #{e.comm}, #{e.deptno});
</foreach>
</insert>
<insert id="bigInsert2">
insert into emp(empno, ename, job, mgr, hiredate, sal, comm, deptno)
<foreach collection="emp" close=")" item="e" separator="union all"
open="select emp_seq.nextval, ename, job, mgr, hiredate, sal, comm, deptno from(">
select #{e.ename} ename, #{e.job} job, #{e.mgr} mgr, #{e.hiredate} hiredate,
#{e.sal} sal, #{e.comm} comm, #{e.deptno} deptno
from dual
</foreach>
</insert>
<update id="bigUpdate">
<foreach collection="list" item="v" open="begin" close="end;">
update emp
<set>
ename = #{v}
</set>
<where>
ename in('aaa', 'bbb');
</where>
</foreach>
</update>
<delete id="bigDelete">
delete from emp
<where>
ename in
<foreach collection="list" item="v" separator="," open="(" close=")">
#{v}
</foreach>
</where>
</delete>
※簡單的新增和查詢都必需在最前加上 begin,和最後加上 end; 否則報錯
※第二種新增看起來較複雜,以下是 SQL
insert into table_name(id, f1, f2)
select emp_seq.nextval, f1, f2 from (
select 'xxx1' f1, 'ttt1' f2 from dual
union all
select 'xxx2' f1, 'ttt2' f2 from dual
union all
select 'xxx3' f1, 'ttt3' f2 from dual
)
MySQL:
mysql 可以不用 begin end; 即可新增,但必須在 jdbc.url 後加東西,jdbc.url=jdbc:mysql://localhost:3306/test?allowMultiQueries=true另外還有一種是 insert into () values(),(),(),Oracle 沒有
<insert id="bigInsert1">
<foreach collection="emps" item="emp" separator=";">
insert into emp(t1,t2,t3) values
(#{emp.f1},#{emp.f2},#{emp.f3},#{emp.f4})
</foreach>
</insert>
<insert id="bigInsert2">
insert into emp(t1,t2,t3) values
<foreach collection="emps" item="emp" separator=",">
(#{emp.f1},#{emp.f2},#{emp.f3})
</foreach>
</insert>

沒有留言:
張貼留言