Hibernate - 自定义值生成策略(字段值自动填充)

218 阅读2分钟

在项目开发过程中通常会有需要自动填充字段值的场景,例如自动生成主键id,自动填充创建者姓名和时间等等。Hibernate 本身虽然提供了一些开箱即用的主键生成策略,但仅仅只针对主键,网上关于非主键的自定义生成的文章也较少或较旧,本文将阐述如何完全自定义任意字段的值生成策略。

自定义主键生成策略

1.主键上使用 @GeneratedValue@GenericGenerator

其中 snowflakeId 是自定义的字符串,可以取任意不重复字符,在 hibernate6.2 及之后可通过type直接指定生成策略的类,在之前需通过 strategy = "com.seepine.common.orm.SnowflakeIdGenerator" 指定生成类的全路径

  @Id
  @GeneratedValue(generator = "snowflakeId")
  @GenericGenerator(name = "snowflakeId", type = SnowflakeIdGenerator.class)
  private String id;

2.编写 SnowflakeIdGenerator.class

public class SnowflakeIdGenerator implements IdentifierGenerator {

  @Override
  public Serializable generate(SharedSessionContractImplementor session, Object object)
      throws HibernateException {
    // 此处返回要填充的主键值即可,例如可以雪花id、可以全局发号器获取等等
    return String.valueOf(YitIdHelper.nextId());
  }
}

自定义非主键生成策略

本章以自动填充用户id为例,其他场景以此类推即可

1.自定义生成注解

使用 @ValueGenerationType 并指定生成策略类

@ValueGenerationType(generatedBy = UserIdGeneration.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface UserIdGenerator {
  EventType[] event() default {EventType.INSERT, EventType.UPDATE};
  // 若有其他需要传递的值,自行增加字段即可
}

2.编写 UserIdGeneration.class

public class UserIdGeneration implements BeforeExecutionGenerator {
  UserIdGenerator generator;

  public UserIdGeneration(UserIdGenerator generator,
                        Member member,
                        GeneratorCreationContext creationContext) {
    // 保存到字段上的注解对象
    this.generator = generator;
  }

  // 此方法返回要填充的值
  @Override
  public Object generate(
      SharedSessionContractImplementor session,
      Object owner,
      Object currentValue,
      EventType eventType) {
    // 例如 entity 已经设置了值,则直接使用设置的值
    if (currentValue != null) {
      return currentValue;
    }
    // 否则,通过security/secret等登录鉴权框架获取当前登录者信息,再返回
    AuthUser user = AuthUtil.getUser();
    return user.getId();
  }

  // 此方法返回是插入还是更新生效,此处通过注解动态指定
  @Override
  public EnumSet<EventType> getEventTypes() {
    return EventTypeSets.fromArray(generator.event());
  }
}

3.使用

在要填充的字段上使用自定义的注解即可

  @UserIdGenerator
  private String createId;

若想仅在更新时填充,通过注解传入即可

  @UserIdGenerator(event = EventType.UPDATE)
  private String createId;

博客内容遵循:署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议 本文永久链接是:seepine.com/quarkus/hib…