mybatis免sql外掛之JpaMapper-以Jpa hibernate的風格寫mybatis(生成自定義的MappedStatement)
mybatis免sql外掛之JpaMapper-以Jpa hibernate的風格寫mybatis(生成自定義的MappedStatement)
簡介
JpaMapper以Jpa hibernate的風格寫mybatis的程式碼,可以減少手動寫sql的煩惱。
優勢:
- 不替換底層實現,僅生成sql並交給mybatis
- 方法基本與Jpa hibernate相似,易於框架替換,當然,沒那麼厲害,不支援聯表哦,專案還在繼續完善中。
- 提供簡單分表功能
- 邏輯簡單,可以拿去自己定製
gitee地址:https://gitee.com/xiaoyaofeiyang/JpaMapper
github地址:https://github.com/feiyangtianyao/jpa-mapper
上篇作為起始篇,介紹一下如何從spring容器中獲取到mybatis的mapper/bean。
這一篇將介紹生成自定義的MappedStatement的過程。
mybatis的註解解析MapperAnnotationBuilder
mybatis的註解解析方法位於MapperAnnotationBuilder中。
- parseStatement負責解析每個方法上的sql語句
- buildSqlSourceFromStrings負責生成SqlSource
- MapperBuilderAssistant負責將SqlSource存入mybatis的管理器中。
- handleSelectKeyAnnotation負責處理SelectKey註解,屬於主鍵id回返的策略
當然,裡面的方法不止這些,我們需要用的大概就這些了,其他的都是小細節了。
定義自己的解析器JpaMapperAnnotationBuilder
這裡就只說主要內容了,其他從簡。
-
首先我們需要確定我們的方法型別是屬於增刪改查的哪一種
-
根據方法名確定我們生成的sql語句
在這之前,我們還是要先拿到mapper介面定義的泛型,並分析泛型類的欄位,拿到我們想要的資訊,比如欄位對應、id欄位及策略、分表字段等
生成SqlSource
根據我們前面拿到的資訊生成sql,並將sql使用languageDriver.createSqlSource建立mybatis需要的SqlSource。
public static SqlSource createSqlSource(JpaModelEntity jpaModelEntity, Method method, SqlType sqlCommandType,
Class<?> parameterTypeClass, LanguageDriver languageDriver, Configuration configuration) {
try {
String sql = "";
if(jpaModelEntity.isSharding()){
sql = createShardingSql(jpaModelEntity, method, sqlCommandType);
}else{
sql = createCommonSql(jpaModelEntity, method, sqlCommandType);
}
if (StringUtil.isEmpty(sql))
return null;
return languageDriver.createSqlSource(configuration, sql, parameterTypeClass);
} catch (Exception e) {
throw new BuilderException("Could not find value method on SQL annotation. Cause: " + e, e);
}
}
生成Sql
這裡僅以findBy + 欄位做說明
mybatis查詢結果一般作為實體或list返回,所以,findBy操作我們將返回Collection,這個可以不管,寫的時候定義什麼就是什麼。
查詢欄位
查詢欄位使用前面分析好的泛型類的欄位,使用@Column註解獲取資料庫欄位的名稱。因此我們可以生成select的字首:
select 資料庫欄位 as 成員名稱 , (…)
表名
表名我們使用@Table註解指定。所有我們可以寫成:
from 表名
查詢條件
findBy + 欄位 (and)做查詢時,查詢條件要把方法名做解析後獲得。
String[] params = 方法名.split(“And|and|AND”);
根據方法名引數,我們可以找到對應的查詢條件:
where 條件1(param在實體中的資料庫對應名稱) = #{實體中的成員名稱} and (…)
至此,一個簡單的findBy寫好了。其他的方法將不再贅述。