hibernate - 自定義註解

背景

  • hibernate自身提供一些註解可供使用,例如:@CreationTimestamp(新增實體時,生成建立時間)、@UpdateTimestamp(新增或更新實體時,生產更新時間)等。那若是咱們指望自定義時間的生成策略時,要如何實現呢?例如:新增實體時,若是某個字段有值,就用該值;若是沒有,則使用某個策略生成某個值

實現

  • 功能:自定義@CreateTime,被該註解修飾的字段,若是字段有值,則使用該值;若是該字段沒值,則使用當前時間
  • 具體代碼:
/** * 被@CreateTime註解的字段的值生成器 * ps.暫時只支持,Timestamp,java.util.Date,java.sql.Date這三種類型 * */
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;
    }
}
複製代碼
/** * 被@CreateTime註解的字段的值生成策略: * 1.insert的時候觸發 * 2.若是該字段已有值,直接使用該值,不然使用當前時間 * */
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的字段上進行註解便可
相關文章
相關標籤/搜索