SSM-動態SQL
動態SQL主要是解決同一類SQL語句匹配不同的問題,舉個栗子:
加入我要執行一個查詢語句,但是是一個不確定的查詢語句,可能會根據ID去查,如果ID沒有就可能根據名字去查,或者說同時根據兩個去查。那么這時候SQL語句就是不確定的,就要用到mybatis
的動態
SQL語句了,同時Mybatis是基於OGNL表達式的。
動態SQL語句
- if
- where
- choose
- when
- otherwise
- set
- trim
- foreach
- sql
- include
- bind
數據形式
id | the_name | flower |
---|---|---|
1 | 小明 | 小紅花 |
if
if
很簡單的知道,就是判斷條件的。
xml映射文件配置文件
<!--動態SQL if語句-->
<select id="query1" resultType="com.weno.pojo.Girl">
select * from Girl where
<if test= "the_name != null">
the_name = #{the_name}
</if>
<if test= "flower != null">
and flower = #{flower};
</if>
</select>
@Test
public void m006() {
SqlSession sqlSession = MybatisUtil.getSession();
GirlMapper mapper = sqlSession.getMapper(GirlMapper.class);
Girl g= new Girl();
g.setName("小明");
// g.setFlower("小紅花");
Girl girl=mapper.query1(g);
sqlSession.commit();
sqlSession.close();
System.out.printf(girl.toString());
}
如果此時我們將小紅花
注釋掉查看一下運行結果:
DEBUG [main] - ==> Preparing: select * from Girl where the_name = ?
DEBUG [main] - ==> Parameters: 小明(String)
TRACE [main] - <== Columns: id, the_name, flower
TRACE [main] - <== Row: 1, 小明, 小紅花
DEBUG [main] - <== Total: 1
在SQL語句中並沒有加上flower
語句。但是此時卻有一個問題,如果the_name
為null
,而flower
不為null
,那么在SQL語句中豈不是多了一個and
,變成了:
DEBUG [main] - ==> Preparing: select * from Girl where and flower = ?;
這時候程序肯定報錯,那么我們該如何處理呢?那么接下來說一下where
標簽。
where
任然使用上面的例子:
<select id="query2" resultType="com.weno.pojo.Girl">
select * from Girl
<where>
<if test="the_name != null">
and the_name = #{the_name}
</if>
<if test="flower != null">
and flower = #{flower}
</if>
</where>
</select>
這個跟上面的區別就是將where
改成了<where>
標簽。
<where>
在這里的作用就是當標簽中有返回值時,就插入一個where
,同時,如果標簽是以AND
或OR
【不區分大小寫】開頭
時,就剔除。
choose
choose語句有點類似Java中的switch,當有一個符合時,就選擇那一個並跳出。
映射文件
<select id="query3" resultType="com.weno.pojo.Girl">
select * from Girl where
<choose>
<when test="id != null and id!=''">
id = #{id}
</when>
<when test="the_name != null and the_name != ''">
the_name = #{the_name}
</when>
<otherwise>
flower = #{flower}
</otherwise>
</choose>
</select>
在這種情況下,如果id符合的話,就不會再考慮下面的了。
@Test
public void m008() {
SqlSession sqlSession = MybatisUtil.getSession();
GirlMapper mapper = sqlSession.getMapper(GirlMapper.class);
Girl g= new Girl();
g.setId(1);
g.setName("小明");
g.setFlower("小紅花");
Girl girl=mapper.query3(g);
sqlSession.commit();
sqlSession.close();
System.out.printf(girl.toString());
}
SQL語句,在其中並沒有選擇the_name
DEBUG [main] - ==> Preparing: select * from Girl where id = ?
set
set是一個更新數據的標簽
<update id="update1">
update Girl set the_name=#{the_name},flower=#{flower} where id=#{id};
</update>
java代碼:
@Test
public void m009() {
SqlSession sqlSession = MybatisUtil.getSession();
GirlMapper mapper = sqlSession.getMapper(GirlMapper.class);
Girl g= new Girl();
g.setId(1);
g.setName("小紅");
// g.setFlower("小明花");
mapper.update1(g);
sqlSession.commit();
sqlSession.close();
}
如果此時這樣執行,那么在數據庫表里面,flower
的數據即為null
。假如此時,使用if
標簽
<update id="update2">
update Girl set
<if test="the_name != null and the_name != ''">
the_name=#{the_name},
</if>
<if test="flower != null and flower != ''">
flower=#{flower}
</if>
where id=#{id};
</update>
那么此時會出現一個問題,如果第一個符合,而第二個不符合,那么就會多一個,
,此時使用<set>
標簽就可以解決這個問題
<update id="update3">
update Girl
<set>
<if test="the_name != null and the_name != ''">
the_name=#{the_name},
</if>
<if test="flower != null and flower != ''">
flower=#{flower},
</if>
</set>
where id=#{id};
</update>
<set>
標簽和<where>
有點類似,在<set>
標簽中,如果結尾有逗號,就將逗號去除。
trim
<trim>
就很神奇了,它既可以實現<set>
的功能,也能夠實現<where>
的功能。
trim可以在前面增加和刪除內容,也可在在后面也執行此操作。
<update id="query0">
<trim prefixOverrides="and | or">
<if test="the_name != null">
and the_name = #{the_name}
</if>
<if test="flower != null">
and flower = #{flower}
</if>
</trim>
</update>
去除第一個and或則是or
- prefix:前綴
- prefixoverride:去掉第一個a
- suffix:后綴
- suffixoverride:去掉最后一個
foreach
foreach 類似for循環。
改寫我們用 foreach 來改寫 select * from Girl where id in (1,2,3)
映射文件
<!-- collection:指定輸入對象中的集合屬性,使用@Param("ids")指令名字 item:每次遍歷生成的對象 open:開始遍歷時的拼接字符串 close:結束時拼接的字符串 separator:遍歷對象之間需要拼接的字符串 select * from Girl where id in (1,2,3) -->
<select id="queryByIDs" resultType="com.weno.pojo.Girl">
select * from Girl where
<foreach collection="ids" item="id" open="id in (" close=" ) " separator=",">
#{id}
</foreach>
</select>
sql
SQL片段主要是為了提高效率,可以講動態SQL的判斷部分獨立處理,提高程序的復用率。
<!-- id是sql片段的標識,一定要唯一 -->
<sql id="sql_1">
<if test="the_name != null and the_name != ''">
the_name = #{the_name}
</if>
</sql>
注意:在SQL片段中,不要包括where
include
引用SQL片段,使用上面的例子
<select id="query2" resultType="com.weno.pojo.Girl">
select * from Girl
<where>
<include refid="sql_1"/>
<if test="flower != null">
and flower = #{flower}
</if>
</where>
就是如此簡單。
bind
<bind>
簡單的來說,就是使值變成另外一個。
例如在模糊查詢語句中要使傳入的值變成%*%
,那么就使用bind進行連接。
<select id="queryLikeByName" resultType="com.weno.pojo.Girl">
select * from Girl
<bind name="_name" value="'%'+the_name+'%'"/>
<!-- 如果the_name代表A,那么_name則代表%A% -->
where the_name like #{_name}
</select>
mybati的動態語句大概就這樣了,如果學會了使用,那么毋庸置疑,可以大量的提高我們的效率。
不過更多的mybatis的使用,可以參考mybatis的 官方文檔
媽耶,第一次寫這么多的字,紀念一下!!