mybatis免sql外掛之JpaMapper-以Jpa hibernate的風格寫mybatis(主鍵賦值策略及useGeneratedKeys無效的坑)
mybatis免sql外掛之JpaMapper-以Jpa hibernate的風格寫mybatis(主鍵賦值策略及useGeneratedKeys無效的坑)
簡介
JpaMapper以Jpa hibernate的風格寫mybatis的程式碼,可以減少手動寫sql的煩惱。
優勢:
- 不替換底層實現,僅生成sql並交給mybatis
- 方法基本與Jpa hibernate相似,易於框架替換,當然,沒那麼厲害,不支援聯表哦,專案還在繼續完善中。
- 提供簡單分表功能
- 邏輯簡單,可以拿去自己定製
gitee地址:https://gitee.com/xiaoyaofeiyang/JpaMapper
github地址:https://github.com/feiyangtianyao/jpa-mapper
上篇介紹生成自定義的MappedStatement的過程。這一篇將介紹主鍵id生成策略,並賦值給id欄位供後續使用。
mybatis的KeyGenerator
KeyGenerator是主鍵生成策略的介面,實現KeyGenerator的類主要有三個:
- Jdbc3KeyGenerator,其實就是自增策略
- NoKeyGenerator,顧名思義就是啥也沒有。
- SelectKeyGenerator,解析SelectKey註解定義的主鍵策略。
當然,裡面的方法不止這些,我們需要用的大概就這些了,其他的都是小細節了。
useGeneratedKeys無效的坑
在使用註解的時候,我們希望取回id主鍵,往往在方法上加上@Options(useGeneratedKeys=true),這樣的情況下,我們可能會無法正常拿回id,有的人說我的就有效啊,是因為引數的寫法不同,下面會介紹。這時你去百度搜下答案,會發現網上都是說把int返回值當成主鍵之類的廢話。
都是文不對題,這裡不再贅述,其實@Options(useGeneratedKeys=true)是有效的,它已經指定了KeyGenerator為Jdbc3KeyGenerator,造成可能無法找回id原因是引數的問題。
只要引數中出現了@Param註解,@Options(useGeneratedKeys=true)就是無效的,@Param註解會把方法的引數作為Map交給後續執行,這樣後續有個Jdbc3KeyGenerator的processAfter方法就會丟擲一個小異常,導致id無法賦值。
當沒有@Param註解的時候,實體就會作為Object給到後續操作,Jdbc3KeyGenerator的processAfter就可以正常執行並賦值。
定義註解實現
為了實現我們自己的主鍵策略(也不能說自己的,是藉助mybatis的),我們可以使用persistence的@GeneratedValue註解,可能沒那麼屌,也沒那個必要,我們就只定義@GeneratedValue(generator=“JDBC”)去對應Jdbc3KeyGenerator。並將Jdbc3KeyGenerator交給MapperBuilderAssistant去生成MappedStatement就行。這樣我們就可以完成自增情況下主鍵id的回返。
當然,為了跟mybatis的功能對應,我們還需要支援SelectKey,但是mybatis的SelectKey是隻能放在方法上的,我們就copy一份,修改下註解的@Target就行。如:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.apache.ibatis.mapping.StatementType;
/**
* @author Clinton Begin
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.FIELD })
public @interface SelectKey {
String[] statement();
String keyProperty();
String keyColumn() default "";
boolean before();
Class<?> resultType();
StatementType statementType() default StatementType.PREPARED;
}
和mybatis的一模一樣,但是可以放在field上了,這樣,我們可以讀取這個註解,並按照mybatis解析SelectKey的方式去解析就可以回返id了,省事省心,還不會錯,排查錯誤也簡單。
介紹完了。
下篇介紹下如何自定義分表(sharding)功能。