在项目开发过程中通常会有需要自动填充字段值的场景,例如自动生成主键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…