背景
- hibernate自身提供一些注解可供使用,例如:@CreationTimestamp(新增实体时,生成创建时间)、@UpdateTimestamp(新增或更新实体时,生产更新时间)等。那如果我们期望自定义时间的生成策略时,要如何实现呢?例如:新增实体时,如果某个字段有值,就用该值;如果没有,则使用某个策略生成某个值
实现
- 功能:自定义@CreateTime,被该注解修饰的字段,如果字段有值,则使用该值;如果该字段没值,则使用当前时间
- 具体代码:
public final class CreateTimeGenerators {
private static final Map<Class<?>, ValueGenerator<?>> GENERATORS;
private CreateTimeGenerators() {
}
static {
GENERATORS = new HashMap<>();
GENERATORS.put(Date.class,
(session, owner) -> {
Date date = new Date();
Object value = ReflectionUtils.getFieldValueWithAnnotation(owner, CreateTime.class);
if (value != null) {
date = (Date) value;
}
return date;
}
);
GENERATORS.put(
java.sql.Date.class,
(session, owner) -> {
java.sql.Date date = new java.sql.Date(System.currentTimeMillis());
Object value = ReflectionUtils.getFieldValueWithAnnotation(owner, CreateTime.class);
if (value != null) {
date = (java.sql.Date) value;
}
return date;
}
);
GENERATORS.put(
Timestamp.class,
(session, owner) -> {
Timestamp date = new Timestamp(System.currentTimeMillis());
Object value = ReflectionUtils.getFieldValueWithAnnotation(owner, CreateTime.class);
if (value != null) {
date = (Timestamp) value;
}
return date;
}
);
}
@SuppressWarnings("unchecked")
public static <T> ValueGenerator<T> get(final Class<T> type) {
final ValueGenerator<?> valueGeneratorSupplier = GENERATORS.get(
type);
if (Objects.isNull(valueGeneratorSupplier)) {
throw new HibernateException(
"Unsupported property type [" + type.getName() + "] for @CreateTime generator annotation");
}
return (ValueGenerator<T>) valueGeneratorSupplier;
}
}
public class CreateTimeGeneration implements AnnotationValueGeneration<CreateTime> {
private ValueGenerator<?> generator;
@Override
public void initialize(CreateTime annotation, Class<?> propertyType) {
generator = CreateTimeGenerators.get(propertyType);
}
@Override
public GenerationTiming getGenerationTiming() {
return GenerationTiming.INSERT;
}
@Override
public ValueGenerator<?> getValueGenerator() {
return generator;
}
@Override
public boolean referenceColumnInSql() {
return false;
}
@Override
public String getDatabaseGeneratedReferencedColumnValue() {
return null;
}
}
@ValueGenerationType(generatedBy = CreateTimeGeneration.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(FIELD)
public @interface CreateTime {
}
public class Human{
@CreateTime
@Column(name = "create_time")
private Date createTime;
}
总结
- hibernate自定义注解实现步骤:
- 自定义一个注解。通过@ValueGenerationType(generatedBy = CreateTimeGeneration.class)的方式指定生成器
- 实现该生成器
- initialize方法对ValueGenerator进行初始化(并指定生成的相关逻辑)
- getGenerationTiming方法指定生成的时机(NEVER/INSERT/ALWAYS)
- 注解使用方式:与hibernate自带的CreationTimestamp一致,直接在Entity的字段上进行注解即可