Spring Boot MyBatis升級篇-註解-動態SQL(if test)-方案二:@Provider(8)
1)動態語言註解
(2)@Provider使用思路
(3)@SelectProvider小試牛刀
(4)@SelectProvider初露鋒芒
(5)@SelectProvider過關斬將
(6)@InsertProvider小弟不敢當
(7)@UpdateProvider你加我來改
(8)@DeleteProvider不高興就刪
接下來看下具體的內容:
(1)動態語言註解
對於創建動態的查的語言。MyBatis提供了多個註解如:@InsertProvider,@UpdateProvider,@DeleteProvider和@SelectProvider,這些都是建立動態語言和讓MyBatis執行這些語言。
(2)@Provider使用思路
對於MyBatis提供的幾個@Provider,裏面最主要的參數是type,也就是sql類的Calss對象,另外就是對應的方法名,我們看SelectProvider的源代碼:
Java代碼 收藏代碼 @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface SelectProvider { Class<?> type(); String method(); }
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface SelectProvider { Class<?> type(); String method(); }
所以要實現動態的SQL查詢,那麽大體的思路就是,編寫一個SqlProvider,比如:DemoSqlProvider,在此方法中返回一條SQL語句即可。然後在Mapper類中使用@SelectProvider註解,指定provider類和對應的SQL方法。
接下來我們來解決上一篇博客的問題:
問題:有一個表中有id,name,email等字段,有這麽一個查詢要求:我們希望的是如果name不為null的話,那麽就當做條件,否則就不要當做條件;如果email不為null,那麽就當做條件,否則不當做條件。
接下裏看看怎麽使用@SelectProvider破。
(3)@SelectProvider小試牛刀
我們先編寫一個DemoSqlProvider,代碼如下:
package com.kfit.demo.mapper; import com.kfit.demo.bean.Demo; public class DemoSqlProvider { /** * 查詢語句. * @param demo * @return */ public String select5(Demo demo){ StringBuffer sql = new StringBuffer("select *from demo where 1=1 "); if(demo.getName() != null){ sql.append(" and name=#{name}"); } if(demo.getEmail() != null){ sql.append(" and email=#{email}"); } return sql.toString(); } }
package com.kfit.demo.mapper; import com.kfit.demo.bean.Demo; public class DemoSqlProvider { /** * 查詢語句. * @param demo * @return */ public String select5(Demo demo){ StringBuffer sql = new StringBuffer("select *from demo where 1=1 "); if(demo.getName() != null){ sql.append(" and name=#{name}"); } if(demo.getEmail() != null){ sql.append(" and email=#{email}"); } return sql.toString(); } }
在DemoMapper中加入查詢方法:
@SelectProvider(type=DemoSqlProvider.class,method="select5") public List<Demo> select5(Demo demo);
@SelectProvider(type=DemoSqlProvider.class,method="select5") public List<Demo> select5(Demo demo);
這裏使用@SelectProvider,不是@Select了。
訪問1:http://127.0.0.1:8080/select4會返回全部數據,動態SQL是:
SELECT * from Demo WHERE 1=1
- SELECT * from Demo WHERE 1=1
訪問2:http://127.0.0.1:8080/select4?name=王五會返回name=王五的數據,動態SQL是:
- SELECT * from Demo WHERE 1=1 and name=?
- SELECT * from Demo WHERE 1=1 and name=?
訪問3:http://127.0.0.1:8080/select4?name=王五&[email protected]會返回name=王五並且[email protected]的數據,動態SQL是:
- SELECT * from Demo WHERE 1=1 and name=? and email=?
- SELECT * from Demo WHERE 1=1 and name=? and email=?
(4)@SelectProvider初露鋒芒
上面的代碼直接純SQL編寫了,可讀性還是相對差了點,MyBatis提供了SQL類(org.apache.ibatis.jdbc.SQL),可以讓代碼看起來更有意義。
在DemoSqlProvider中加入方法:
/** * 查詢語句.使用SQL * @param demo * @return */ public String select6(final Demo demo){ return new SQL(){{ SELECT("id,name,email"); FROM("demo"); if(demo.getName() != null){ WHERE("name=#{name}"); } if(demo.getEmail() != null){ WHERE("email=#{email}"); } }}.toString(); }
在DempMapper中加入代碼:
@SelectProvider(type=DemoSqlProvider.class,method="select6") public List<Demo> select6(Demo demo);
(5)@SelectProvider過關斬將
原以為萬事大吉了,開心的不行,於是乎,信手拈來句代碼,在查詢代碼加入:
PageHelper.startPage(1, 2);整個代碼如下:
@RequestMapping("/select6") public List<Demo> select6(Demo demo){ PageHelper.startPage(1, 2); return demoService.select6(demo); }
@RequestMapping("/select6") public List<Demo> select6(Demo demo){ PageHelper.startPage(1, 2); return demoService.select6(demo); }
運行,訪問:http://127.0.0.1:8080/select6完了,這是什麽鬼: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘providerTakesParameterObject‘ in ‘class org.apache.ibatis.builder.annotation.ProviderSqlSource‘ 出現以上問題,是由於我們使用的PageHelper版本導致的,升級版本即可。
運行,訪問:http://127.0.0.1:8080/select6完了,這是什麽鬼:
nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘providerTakesParameterObject‘ in ‘class org.apache.ibatis.builder.annotation.ProviderSqlSource‘
出現以上問題,是由於我們使用的PageHelper版本導致的,升級版本即可。
原先的版本為:
Xml代碼 收藏代碼 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>4.1.0</version> </dependency> [xml] view plain copy
升級為:
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>4.2.1</version> </dependency>
貌似:4.1.5就支持@SelectProvider分頁查詢了(未進行驗證)。
(6)@InsertProvider小弟不敢當
最麻煩的查詢搞定了之後,這個就簡單了,
在DemoSqlProvider中加入如下代碼:
/** * 查詢語句.使用SQL * @param demo * @return */ public String save3(final Demo demo){ return new SQL(){{ INSERT_INTO("demo"); //多個寫法. INTO_COLUMNS("name","email"); INTO_VALUES("#{name}","#{email}"); //條件寫法. // if(demo.getName() != null){ // VALUES("name","#{name}"); // } // if(demo.getEmail() != null){ // VALUES("email","#{email}"); // } }}.toString(); }
在DemoMapper中加入如下代碼:
ava代碼 收藏代碼 @InsertProvider(type=DemoSqlProvider.class,method="save3") @Options(keyProperty="id",keyColumn="id",useGeneratedKeys=true) public void save3(Demo demo);
(7)@UpdateProvider你加我來改
DemoSqlProvider中的代碼如下:
Java代碼 收藏代碼 /** * @param demo * @return */ public String update2(final Demo demo){ return new SQL(){{ UPDATE("demo"); //條件寫法. if(demo.getName() != null){ SET("name=#{name}"); } if(demo.getEmail() != null){ SET("email=#{email}"); } WHERE("id=#{id}"); }}.toString(); }
在DemoMapper中的代碼:
碼 收藏代碼 @UpdateProvider(type=DemoSqlProvider.class,method="update2") public int update2(Demo demo);
(8)@DeleteProvider不高興就刪
DemoSqlProvider代碼:
Java代碼 收藏代碼 /** * @param demo * @return */ public String delete2(){ return new SQL(){{ DELETE_FROM("demo"); WHERE("id=#{id}"); }}.toString(); }
在DemoMapper中的代碼:
@UpdateProvider(type=DemoSqlProvider.class,method="delete2") public int delete2(int id);
Spring Boot MyBatis升級篇-註解-動態SQL(if test)-方案二:@Provider(8)