一 前言
本篇文章需要有一定得mybatis入門基礎才能學習;如果是初學者請參考以下鏈接進行系統學習
- mybatis入門 https://blog.csdn.net/youku1327/article/details/103339617
- mybatis初級映射 https://blog.csdn.net/youku1327/article/details/103411829
- mybatis配置 https://blog.csdn.net/youku1327/article/details/103604724
當然如果是資深讀者,又沒有經過系統得學習,可以直接入主本篇,帶你一覽動態標簽使用方式;
動態SQL可以通過給定不同得條件,執行不同得SQL語句,實現動態SQL得方式就是通過mybatis提供得標簽語法進行配置;
二 動態SQL標簽
2.1 if 標簽
- if 標簽表示條件判斷
- customer_name 不為空時會執行當前if標簽的內容;此時的sql 語句 就是 select * from
customer
where andcustomer_name
= #{customer_name} - gender不為空時會執行if語句;此時執行的sql語句就是 select * from
customer
where 1 = 1 andgender
= #{gender} - customer_name 和 gender 標簽都不為空時;此時執行的sql語句就是 select * from
customer
where andcustomer_name
= #{customer_name} andgender
= #{gender}
<select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
select
*
from `customer`
where 1=1
<if test="customer_name!=null and customer_name!='' ">
and `customer_name` = #{customer_name}
</if>
<if test="gender!=null and gender!=''">
and `gender` = #{gender}
</if>
</select>
2.2 where 標簽
2.1 中我們在 where 后面使用 1=1 的操作,表示永遠為真,不是一個規范的數據庫操作;我們通常在select 語句的條件部分會使用 where 標簽 與 if 標簽 搭配使用,此時就可以消除 1=1操作帶來的負面影響
<select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
select
*
from `customer`
<where>
<if test="customer_name!=null and customer_name!='' ">
and `customer_name` = #{customer_name}
</if>
<if test="gender!=null and gender!=''">
and `gender` = #{gender}
</if>
</where>
</select>
2.3 choose, when, otherwise標簽
有時候需要一種場景就是 if else 形式的判斷,如下示例中
- 當 customer_name 不為空 會執行 when標簽體的內容;此時sql 就是 select
gender
fromcustomer
; - 當輸入的條件customer_name 為空時會執行otherwise標簽體的內容;此時sql就是 select * from
customer
;
<select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
select
<choose>
<when test="customer_name=!null">
`gender`
</when>
<otherwise>
*
</otherwise>
</choose>
from `customer`
</select>
2.4 trim標簽
先說下trim 屬性 代表的涵義
- prefix 表示前綴,就是會為 trim 標簽體加一個前綴;
- prefixOverrides 表示會將匹配到的第一個字符串去除;
- suffix 表示后綴,會為 trim 標簽體加一個后綴內容;
- suffixOverrides表示會將匹配到的最后一個字符串去除;
如下示例中 執行的SQL語句就是 select * from customer
where customer_name
= #{customer_name}
<select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
select
*
from `customer`
<trim prefix="where" prefixOverrides="and">
and `customer_name` = #{customer_name}
</trim>
</select>
2.5 set標簽
set 標簽 只有在 更新操作中能用到;如下示例中set標簽會默認將最后一個多余的逗號去除;
<update id="updateCustomer" parameterType="com.zszxz.dynamic.entity.Customer">
update `customer`
<set>
<if test="customer_name!=null">
`customer_name` = #{customer_name},
</if>
<if test="gender!=null">
`gender` = #{gender},
</if>
<if test="telephone!=null">
`telephone` = #{telephone},
</if>
<if test="register_time!=null">
`register_time` = #{register_time},
</if>
</set>
<where>
id = #{id}
</where>
</update>
如果所有的參數都不為空 執行的語句如下
update `customer` SET `customer_name` = ?, `gender` = ?, `telephone` = ?, `register_time` = ? WHERE id = ?
set標簽此時會等效於trim標簽的如下形式
<trim prefix="SET" suffixOverrides=",">
...
</trim>
2.6 foreach 標簽實現in
foreach 標簽屬性說明如下
- collection 參數
- open 前綴
- separator 分割符
- item 迭代中取得值,當入參數是Map.Entry或者map就是其 中 得值
- index 迭代中得鍵,當入參數是Map.Entry或者map就是其 中 得鍵;若入參是組數就是索引;
<select id="getCustomerById" resultType="com.zszxz.dynamic.entity.Customer" >
select
*
from `customer`
<where>
<if test="ids!=null">
and id in
<foreach collection="ids" open="(" separator="," item="id" index="i" close=")">
#{id}
</foreach>
</if>
</where>
</select>
最終得SQL語句執行形式如下
select * from `customer` WHERE id in ( ? , ? )
2.7 foreach標簽實現批量插入
在xml中添加如下語句
<insert id="addCustomer" >
insert into `customer`(
`customer_name`,
`gender`,
`telephone`,
`register_time`
)values
<foreach collection="customers" separator="," item="customer" index="i">
(
#{customer.customer_name},
#{customer.gender},
#{customer.telephone},
#{customer.register_time}
)
</foreach>
</insert>
部分測試類如下 在 for循環中創建3 個客戶對象放入List,然后執行批量插入方法
@Test
public void testInsert(){
// 獲得mapper的形式
CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
ArrayList<Customer> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Customer customer = new Customer();
customer.setCustomer_name("知識追尋者");
customer.setGender("男");
customer.setTelephone("999"+i);
list.add(customer);
}
// 添加客戶
mapper.addCustomer(list);
sqlSession.commit();
sqlSession.close();
}
最終執行得SQL語句格式如下
insert into `customer`( `customer_name`, `gender`, `telephone`, `register_time` )values ( ?, ?, ?, ? ) , ( ?, ?, ?, ? ) , ( ?, ?, ?, ? )
2.8 script標簽
script標簽 用於 注解版本得動態SQL,官方示例如下
@Update({"<script>",
"update Author",
" <set>",
" <if test='username != null'>username=#{username},</if>",
" <if test='password != null'>password=#{password},</if>",
" <if test='email != null'>email=#{email},</if>",
" <if test='bio != null'>bio=#{bio}</if>",
" </set>",
"where id=#{id}",
"</script>"})
void updateAuthorValues(Author author);
2.9 sql , include標簽
sql 標簽是個sql片段,如下示例中將查詢條件抽出為一個sql片段,然后使用include標簽實現引用;我們要進行復用sql片段時就很有用,減少代碼量;
<sql id="condition">
<where>
<if test="customer_name!=null and customer_name!='' ">
and `customer_name` = #{customer_name}
</if>
<if test="gender!=null and gender!=''">
and `gender` = #{gender}
</if>
</where>
</sql>
<select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
select
*
from `customer`
<include refid="condition">
</include>
</select>
2.10 bind標簽
bind
元素可以從 OGNL 表達式中創建一個變量並將其綁定到上下文;使用bind標簽好處就是在數據庫替換過程中可以除去不同數據庫語法得影響;如下示例中就可以實現在mysql,oracle,postgresql 中數據替換;如果使用 mysql 得concat 函數在oracle中不再適用;
<sql id="condition">
<where>
<if test="customer_name!=null and customer_name!='' ">
and customer_name like #{customer_name}
</if>
<if test="gender!=null and gender!=''">
and gender = #{gender}
</if>
</where>
</sql>
<select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
<bind name="customer_name" value="'%'+customer_name+'%'"/>
select
*
from customer
<include refid="condition">
</include>
</select>
三 源碼
如果是初學者,有些地方看不懂可以查閱作者得mybatis 專欄說明有源碼地址,源碼中每個示例都有齊全得代碼提供個人學習;