Mybatis實現(xiàn)動態(tài)SQL編寫的示例詳解
前言
上篇博文把表連接查詢和三種對應關(guān)系的寫法記錄總結(jié)了,本篇要把 mybatis 中的動態(tài)sql 的使用以及緩存知識記錄下來。
動態(tài)SQL
在解釋 where if 標簽之前先進行一個模糊查詢的操作。
模糊查詢
如下面一張表:
查詢所有 李 姓人員的信息:
在mapper接口中定義方法:
List<Person> selectName(String name);
在 xml 中編寫 sql 語句:
<select id="selectName" resultMap="personMap"> select * from t_person where person_name like concat('%', #{name}, '%'); </select>
這里的 concat('%', #{name}, '%') 寫法使用了字符串拼接的技巧,這樣在查詢語句里就是 %name% 的模糊查詢了。
如果這樣寫:'%#{name}%' 是不行的,#{}會失效。
編寫測試類:
測試結(jié)果:
可以看到所有 李 姓的人信息被查詢到了。
where if 標簽
姓李的太多,那么我們可以加一個年齡范圍,于是需要增加兩個參數(shù):
這里要注意,參數(shù)在兩個以上需要使用 注解 來綁定。
重點來看 xml中的 sql 語句:
<select id="selectContent" resultMap="personMap"> select * from t_person <where> <if test="name != null and name !=''"> person_name like concat('%',#{name},'%') </if> <if test="ageMin > 0"> and age >= #{ageMin} </if> <if test="ageMax > ageMin"> and age <= #{ageMax} </if> </where> ??????? </select>
可以看到這里的 where 關(guān)鍵字變成了一個標簽 <where>,這是因為:
如果這三個參數(shù)都不填寫的話,where 下的條件就不會起作用,
此條 sql 就變成了查詢所有。
顯然,查詢所有的語法里是沒有 where 關(guān)鍵字的,因此使用標簽代替。
除了使用 <where> 標簽之外,也可以使用類似 1=1 加 and 的方法拼接。
比如: select * from t_person where 1=1 and ...
此外,where 標簽還可以去除多余的 and 前綴。
if 標簽用來做判斷,test 里寫判斷的條件,標簽內(nèi)寫判斷成功后的 sql 語句:
這里就是判斷名字是否為空以及年齡的取值范圍是否合理:
- test 里面的符號正常寫,and 和 or 代表并且和或者。
- sql 語句里,> 是大于的意思,< 是小于的意思。
編寫測試類:
測試結(jié)果:
很明顯,年齡在 20~28 且姓李的只有 “李白” 自己。
update set 標簽
以往的修改操作都是將對象的所有屬性都修改或者重寫一遍,這樣是不合邏輯的,因此可以在修改的 sql 語句里使用 if 標簽來優(yōu)化。
在 mapper 接口中寫方法:
void update(Person person);
在 xml 中編寫 sql:
<update id="update"> update t_person <set> <if test="personName !=null and personName !=''"> person_name = #{personName}, </if> <if test="age !=null"> age = #{age}, </if> <if test="birthday != null and birthday!= ''"> birthday = #{birthday}, </if> <if test=" sex !=null and sex !=''"> sex = #{sex}, </if> <if test="mobile != null and mobile !=''"> mobile = #{mobile}, </if> <if test="address !=null and address!=''"> address = #{address} </if> </set> where person_id = #{personId} </update>
if 標簽想必好理解,但是set 標簽是做什么的呢?原因是:
假如只修改名字,那么 sql 語句將變?yōu)椋?/p>
update t_person set person_name = ?, where ...
可以發(fā)現(xiàn)?占位符后面會有多余的逗號導致 sql 語法錯誤
<set> 標簽會自動去除多余的逗號后綴。
值得注意的是:set 標簽去除,后綴,where 標簽去除and前綴。
foreach 標簽
相信大家都知道foreach 跟循環(huán)有關(guān)系,沒錯,我們可以利用此標簽來完成 批量刪除 操作。
從 sql 的語句來看,批量刪除應該這樣寫:
delete from t_person where person_id in (?,?,?,...)
那么 in 后的形式該怎么用 mybatis 表達出來呢,有括號,不定數(shù)量的逗號…
不急,一步步來,先寫 mapper接口:
void deleteMany(@Param("myIds") int[] ids);
再編寫 sql 語句:
<delete id="deleteMany"> delete from t_person where person_id in <foreach collection="myIds" open="(" close=")" separator="," item="id"> #{id} </foreach> </delete>
利用 foreach 就可以將參數(shù)集合中的值依次放入到 in 后的括號內(nèi):(id,id,id...)
foreach 標簽相關(guān)解釋:
- collection:被循環(huán)的數(shù)組或者集合,注意如果是參數(shù)必須使用@Param 起名
- open : 循環(huán)以什么開始
- close :循環(huán)以什么結(jié)束
- separator: 循環(huán)以什么分割
- item : 每次循環(huán)的元素
編寫測試類(不要忘記手動提交事務(wù)):
測試結(jié)果:
可以看到數(shù)組里的元素依次放入了括號內(nèi),并成功做到了批量刪除。
useGeneratedKeys 獲取插入數(shù)據(jù)的主鍵值
一般我們習慣將表中的主鍵設(shè)為自增長,那么在使用 insert 插入數(shù)據(jù)時,主鍵是不用賦值的,而是用 null 代替。那怎么才能在插入后直接得到該數(shù)據(jù)的主鍵值呢?那就使用 useGeneratedKeys。
來看具體的使用:
<insert id="insert" useGeneratedKeys="true" keyProperty="personId" keyColumn="person_id"> insert into t_person values (null, #{personName}, #{age}, #{sex}, #{birthday}, #{mobile}, #{address}) </insert>
將值設(shè)為 true 后,keyPropetry 的值填寫屬性名,keyColumn 的值填寫表的字段名。
編寫測試類:
@Test public void insert(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); PersonMapper mapper = sqlSession.getMapper(PersonMapper.class); Person person = new Person(null,"微涼",21,"1",new Date(),"1359356123","愛琴海"); mapper.insert(person); sqlSession.commit(); MybatisUtil.closeSqlSession(sqlSession); System.out.println(person); }
測試結(jié)果:
可以看到插入數(shù)據(jù)后的主鍵值為 240,這便是自動獲取的結(jié)果。
Mybatis 緩存
有關(guān) IO 操作一般都會很耗時,在一個 javaweb 項目中,頁面到 tomcat 與 tomcat 到數(shù)據(jù)庫都屬于IO操作。因此 mybatis 在 tomcat 中創(chuàng)建了一塊叫做緩存的空間,在緩存中保存比如查詢操作的數(shù)據(jù),以后進行重復操作時,就不必到數(shù)據(jù)庫中獲取了,而是直接在 tomcat 內(nèi)部獲取。
如果對數(shù)據(jù)庫進行修改,緩存中的數(shù)據(jù)跟數(shù)據(jù)庫中的對應不上,那么此時緩存中的就變成了臟數(shù)據(jù)。
一級緩存
特點:
- 默認開啟
- 作用在同一個 SqlSession 中
- 臟數(shù)據(jù)的處理: 一旦執(zhí)行增刪改,立刻清空緩存
但是一級緩存并沒有什么意義,因為作用范圍的緣故,它只能在一個 SqlSession ,也就是一個事務(wù)內(nèi),一旦提交事務(wù),緩存就會被清空,沒有實戰(zhàn)意義。
二級緩存
二級緩存的作用范圍大,符合實戰(zhàn)的需求,該如何開啟:
1.實體類需要實現(xiàn)可序列化接口:implements Serializable
2.在 mybatis-config.xml 文件中添加<settings> 標簽:
<!--開啟二級緩存 settings 寫在 properties 和 typeAliases 之間--> <settings> <setting name="cacheEnabled" value="true"/> </settings>
3.在對應 mapper 的 xml 文件中添加 <cache> 標簽:
<cache size="1024" eviction="LRU" flushInterval="60000"/>
size:定義二級緩存空間大小 (單位是 M)
eviction:定義緩存到達上限時的淘汰策略,常使用LRU算法:
叫做最近最久未使用算法,即清空最近使用次數(shù)最少的緩存
flushInterval:定義清空緩存的間隔時間 (單位 ms)
作用范圍:
同一個sqlSessionFactory內(nèi),而且必須提交事務(wù)。
臟數(shù)據(jù)的處理:
1.一旦執(zhí)行增刪改,默認清空同一個 namespace 下的二級緩存。
2.自定義清空緩存的策略:
- flushCache屬性,值為 true 時執(zhí)行清空緩存,為 false 則不清空。
- 在 insert、delete、update 標簽里默認為 true
- 在 select 標簽里默認為 false
臟數(shù)據(jù)并不都是一定要清空,因此在增刪改查標簽內(nèi)可以自由的設(shè)定緩存清空的策略。
到此這篇關(guān)于Mybatis實現(xiàn)動態(tài)SQL編寫的示例詳解的文章就介紹到這了,更多相關(guān)Mybatis動態(tài)SQL內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java基本教程之java線程等待與java喚醒線程 java多線程教程
這篇文章主要介紹了對線程等待/喚醒方法,文中使用了多個示例,大家參考使用吧2014-01-01懶人 IDEA 插件推薦: EasyCode 一鍵幫你生成所需代碼(Easycode用法)
這篇文章主要介紹了懶人 IDEA 插件推薦: EasyCode 一鍵幫你生成所需代碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08springMVC前臺傳數(shù)組類型,后臺用list類型接收實例代碼
這篇文章主要介紹了springMVC前臺傳數(shù)組類型,后臺用list類型接收實例代碼,具有一定借鑒價值,需要的朋友可以參考下。2017-12-12基于Mybatis Plus實現(xiàn)多表分頁查詢的示例代碼
這篇文章主要介紹了基于Mybatis Plus實現(xiàn)多表分頁查詢的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12SpringBoot環(huán)境Druid數(shù)據(jù)源使用及特點
Druid 是目前比較流行的高性能的,分布式列存儲的OLAP框架(具體來說是MOLAP)。本文給大家分享SpringBoot環(huán)境Druid數(shù)據(jù)源使用及特點介紹,感興趣的朋友跟隨小編一起看看吧2021-07-07