mybatis免sql插件之JpaMapper-以Jpa hib
mybatis免sql插件之JpaMapper-以Jpa hibernate的风格写mybatis(主键赋值策略及useGeneratedKeys无效的坑)
简介
JpaMapper以Jpa hibernate的风格写mybatis的代码,可以减少手动写sql的烦恼。
优势:
- 不替换底层实现,仅生成sql并交给mybatis
- 方法基本与Jpa hibernate相似,易于框架替换,当然,没那么厉害,不支持联表哦,项目还在继续完善中。
- 提供简单分表功能
- 逻辑简单,可以拿去自己定制
- 提供分页排序功能,最简单的方法实现分页!
gitee地址:https://gitee.com/ffch/JpaMapper
github地址:https://github.com/ffch/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)功能。