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)功能。

猜你喜欢

转载自blog.csdn.net/feiyangtianyao/article/details/84562150