1. 程式人生 > >mybatis免sql外掛之JpaMapper-以Jpa hibernate的風格寫mybatis(主鍵賦值策略及useGeneratedKeys無效的坑)

mybatis免sql外掛之JpaMapper-以Jpa hibernate的風格寫mybatis(主鍵賦值策略及useGeneratedKeys無效的坑)

mybatis免sql外掛之JpaMapper-以Jpa hibernate的風格寫mybatis(主鍵賦值策略及useGeneratedKeys無效的坑)

簡介

JpaMapper以Jpa hibernate的風格寫mybatis的程式碼,可以減少手動寫sql的煩惱。

優勢:

  1. 不替換底層實現,僅生成sql並交給mybatis
  2. 方法基本與Jpa hibernate相似,易於框架替換,當然,沒那麼厲害,不支援聯表哦,專案還在繼續完善中。
  3. 提供簡單分表功能
  4. 邏輯簡單,可以拿去自己定製

gitee地址:https://gitee.com/xiaoyaofeiyang/JpaMapper

github地址:https://github.com/feiyangtianyao/jpa-mapper

上篇介紹生成自定義的MappedStatement的過程。這一篇將介紹主鍵id生成策略,並賦值給id欄位供後續使用。

mybatis的KeyGenerator

KeyGenerator是主鍵生成策略的介面,實現KeyGenerator的類主要有三個:

  1. Jdbc3KeyGenerator,其實就是自增策略
  2. NoKeyGenerator,顧名思義就是啥也沒有。
  3. 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)功能。