第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

通用枚舉 JPA AttributeConverter 實(shí)現(xiàn)

通用枚舉 JPA AttributeConverter 實(shí)現(xiàn)

阿波羅的戰(zhàn)車 2024-01-28 20:25:14
我試圖解決的問(wèn)題我正在嘗試為 Hibernate 實(shí)現(xiàn)枚舉映射。到目前為止,我已經(jīng)研究了可用的選項(xiàng),并且@Enumerated(EnumType.ORDINAL)和似乎都@Enumerated(EnumType.STRING)不足以滿足我的需求。這@Enumerated(EnumType.ORDINAL)似乎很容易出錯(cuò),因?yàn)閮H僅對(duì)枚舉常量進(jìn)行重新排序就會(huì)搞亂映射,而且這也@Enumerated(EnumType.STRING)不夠,因?yàn)槲沂褂玫臄?shù)據(jù)庫(kù)已經(jīng)充滿了要映射的值,而這些值并不是什么我希望我的枚舉常量被命名為(值是外語(yǔ)字符串/整數(shù))。目前,所有這些值都被映射到字符串/整數(shù)屬性。同時(shí),屬性應(yīng)該只允許有限的值集(想象一下meetingStatus屬性允許字符串:PLANNED、CANCELED和DONE?;蛘吡硪粋€(gè)屬性允許有限的整數(shù)值集:1、2、3、4、5)。我的想法是用枚舉替換實(shí)現(xiàn)以提高代碼的類型安全性。String / Integer 實(shí)現(xiàn)可能導(dǎo)致錯(cuò)誤的一個(gè)很好的例子是表示此類值的 String 方法參數(shù) - 使用 String 時(shí),任何內(nèi)容都會(huì)發(fā)生。另一方面,擁有 Enum 參數(shù)類型會(huì)引入編譯時(shí)安全性。到目前為止我最好的方法似乎滿足我需求的唯一解決方案是為每個(gè)枚舉實(shí)現(xiàn)javax.persistence.AttributeConverter帶有@Converter注釋的自定義。由于我的模型需要相當(dāng)多的枚舉,因此為每個(gè)枚舉編寫(xiě)自定義轉(zhuǎn)換器很快就開(kāi)始變得瘋狂。因此,我尋找問(wèn)題的通用解決方案 - >如何為任何類型的枚舉編寫(xiě)通用轉(zhuǎn)換器。以下答案在這里有很大幫助: https: //stackoverflow.com/a/23564597/7024402。答案中的代碼示例提供了某種通用的實(shí)現(xiàn),但對(duì)于每個(gè)枚舉,仍然需要一個(gè)單獨(dú)的轉(zhuǎn)換器類。答案的作者還繼續(xù)說(shuō)道:“另一種方法是定義一個(gè)自定義注釋,修補(bǔ) JPA 提供程序以識(shí)別該注釋。這樣,您可以在構(gòu)建映射信息時(shí)檢查字段類型,并將必要的枚舉類型提供給純通用轉(zhuǎn)換器?!边@就是我認(rèn)為我會(huì)感興趣的。不幸的是,我找不到更多關(guān)于此的信息,并且我需要更多的指導(dǎo)來(lái)了解需要做什么以及它如何與這種方法一起工作。目前的實(shí)施public interface PersistableEnum<T> {    T getValue();}public enum IntegerEnum implements PersistableEnum<Integer> {    ONE(1),    TWO(2),    THREE(3),    FOUR(4),    FIVE(5),    SIX(6);    private int value;    IntegerEnum(int value) {        this.value = value;    }    @Override    public Integer getValue() {        return value;    }}public abstract class PersistableEnumConverter<E extends PersistableEnum<T>, T> implements AttributeConverter<E, T> {    private Class<E> enumType;    public PersistableEnumConverter(Class<E> enumType) {        this.enumType = enumType;    }    @Override    public T convertToDatabaseColumn(E attribute) {        return attribute.getValue();    }    @Override    public E convertToEntityAttribute(T dbData) {        for (E enumConstant : enumType.getEnumConstants()) {            if (enumConstant.getValue().equals(dbData)) {                return enumConstant;            }        }        throw new EnumConversionException(enumType, dbData);    }}這就是我能夠?qū)崿F(xiàn)部分通用轉(zhuǎn)換器實(shí)現(xiàn)的方式。目標(biāo):無(wú)需為每個(gè)枚舉創(chuàng)建新的轉(zhuǎn)換器類。
查看完整描述

3 回答

?
Qyouu

TA貢獻(xiàn)1786條經(jīng)驗(yàn) 獲得超11個(gè)贊

幸運(yùn)的是,您不應(yīng)該為此修補(bǔ)休眠狀態(tài)。


您可以聲明如下所示的注釋:

import java.lang.annotation.Retention;

import java.lang.annotation.Target;

import java.sql.Types;


import static java.lang.annotation.ElementType.METHOD;

import static java.lang.annotation.ElementType.FIELD;

import static java.lang.annotation.RetentionPolicy.RUNTIME;



@Target({METHOD, FIELD}) 

@Retention(RUNTIME)

public @interface EnumConverter

{

   Class<? extends PersistableEnum<?>> enumClass() default IntegerEnum.class;


   int sqlType() default Types.INTEGER;

}

Hibernate 用戶類型如下:

import java.io.Serializable;

import java.lang.annotation.Annotation;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Types;

import java.util.Objects;

import java.util.Properties;


import org.hibernate.HibernateException;

import org.hibernate.engine.spi.SharedSessionContractImplementor;

import org.hibernate.usertype.DynamicParameterizedType;

import org.hibernate.usertype.UserType;


public class PersistableEnumType implements UserType, DynamicParameterizedType

{

   private int sqlType;

   private Class<? extends PersistableEnum<?>> clazz;


   @Override

   public void setParameterValues(Properties parameters)

   {

      ParameterType reader = (ParameterType) parameters.get(PARAMETER_TYPE);


      EnumConverter converter = getEnumConverter(reader);

      sqlType = converter.sqlType();

      clazz = converter.enumClass();

   }


   private EnumConverter getEnumConverter(ParameterType reader)

   {

      for (Annotation annotation : reader.getAnnotationsMethod()){

         if (annotation instanceof EnumConverter) {

            return (EnumConverter) annotation;

         }

      }

      throw new IllegalStateException("The PersistableEnumType should be used with @EnumConverter annotation.");

   }


   @Override

   public int[] sqlTypes()

   {

      return new int[] {sqlType};

   }


   @Override

   public Class<?> returnedClass()

   {

      return clazz;

   }


   @Override

   public boolean equals(Object x, Object y) throws HibernateException

   {

      return Objects.equals(x, y);

   }


   @Override

   public int hashCode(Object x) throws HibernateException

   {

      return Objects.hashCode(x);

   }


   @Override

   public Object nullSafeGet(ResultSet rs,

         String[] names,

         SharedSessionContractImplementor session,

         Object owner) throws HibernateException, SQLException 

   {

      Object val = null;

      if (sqlType == Types.INTEGER) val = rs.getInt(names[0]);

      if (sqlType == Types.VARCHAR) val = rs.getString(names[0]);


      if (rs.wasNull()) return null;


      for (PersistableEnum<?> pEnum : clazz.getEnumConstants())

      {

         if (Objects.equals(pEnum.getValue(), val)) return pEnum;

      }

      throw new IllegalArgumentException("Can not convert " + val + " to enum " + clazz.getName());

   }


   @Override

   public void nullSafeSet(PreparedStatement st,

         Object value,

         int index,

         SharedSessionContractImplementor session) throws HibernateException, SQLException

   {

      if (value == null) {

         st.setNull(index, sqlType);

      }

      else {

         PersistableEnum<?> pEnum = (PersistableEnum<?>) value;

         if (sqlType == Types.INTEGER) st.setInt(index, (Integer) pEnum.getValue());

         if (sqlType == Types.VARCHAR) st.setString(index, (String) pEnum.getValue());

      }

   }


   @Override

   public Object deepCopy(Object value) throws HibernateException

   {

      return value;

   }


   @Override

   public boolean isMutable()

   {

      return false;

   }


   @Override

   public Serializable disassemble(Object value) throws HibernateException

   {

      return Objects.toString(value);

   }


   @Override

   public Object assemble(Serializable cached, Object owner) throws HibernateException

   {

      return cached;

   }


   @Override

   public Object replace(Object original, Object target, Object owner) throws HibernateException

   {

      return original;

   }

}


然后,您可以使用它:

import org.hibernate.annotations.Type;


@Entity

@Table(name="TST_DATA")

public class TestData

{

   ...


   @EnumConverter(enumClass = IntegerEnum.class, sqlType = Types.INTEGER)

   @Type(type = "com.example.converter.PersistableEnumType")

   @Column(name="INT_VAL")

   public IntegerEnum getIntValue()

   ...


   @EnumConverter(enumClass = StringEnum.class, sqlType = Types.VARCHAR)

   @Type(type = "com.example.converter.PersistableEnumType")

   @Column(name="STR_VAL")

   public StringEnum getStrValue()

   ...

}


另請(qǐng)參閱Bauer、King、Gregory 撰寫(xiě)的優(yōu)秀著作“Java Persistence with Hibernate”中的第5.3.3 章“Extending Hibernate with UserTypes ” 。


查看完整回答
反對(duì) 回復(fù) 2024-01-28
?
墨色風(fēng)雨

TA貢獻(xiàn)1853條經(jīng)驗(yàn) 獲得超6個(gè)贊

我嘗試了 1000 次創(chuàng)造相同的東西。動(dòng)態(tài)為每個(gè)枚舉生成轉(zhuǎn)換器 - 沒(méi)問(wèn)題,但它們將具有相同的類。主要問(wèn)題是:org.hibernate.boot.internal.MetadataBuilderImpl#applyAttributeConverter(java.lang.Class<? extends javax.persistence.AttributeConverter>, boolean)。


如果轉(zhuǎn)換器已經(jīng)注冊(cè),我們會(huì)得到異常。


public void addAttributeConverterInfo(AttributeConverterInfo info) {

        if ( this.attributeConverterInfoMap == null ) {

            this.attributeConverterInfoMap = new HashMap<>();

        }


        final Object old = this.attributeConverterInfoMap.put( info.getConverterClass(), info );


        if ( old != null ) {

            throw new AssertionFailure(

                    String.format(

                            "AttributeConverter class [%s] registered multiple times",

                            info.getConverterClass()

                    )

            );

        }

    }

也許我們可以更改org.hibernate.boot.internal.BootstrapContext Impl,但我確信它會(huì)創(chuàng)建過(guò)于復(fù)雜且不靈活的代碼。


查看完整回答
反對(duì) 回復(fù) 2024-01-28
?
一只萌萌小番薯

TA貢獻(xiàn)1795條經(jīng)驗(yàn) 獲得超7個(gè)贊

簡(jiǎn)化:


import com.pismo.apirest.mvc.enums.OperationType;

import com.pismo.apirest.mvc.enums.support.PersistableEnum;


import java.util.Objects;

import java.util.Optional;

import java.util.stream.Stream;

import javax.persistence.AttributeConverter;

import javax.persistence.Converter;


import lombok.NonNull;

import lombok.RequiredArgsConstructor;


@SuppressWarnings("unused")

public interface EnumsConverters {


    @RequiredArgsConstructor

    abstract class AbstractPersistableEnumConverter<E extends Enum<E> & PersistableEnum<I>, I> implements AttributeConverter<E, I> {


        private final E[] enumConstants;


        public AbstractPersistableEnumConverter(@NonNull Class<E> enumType) {

            enumConstants = enumType.getEnumConstants();

        }



        @Override

        public I convertToDatabaseColumn(E attribute) {

            return Objects.isNull(attribute) ? null : attribute.getId();

        }


        @Override

        public E convertToEntityAttribute(I dbData) {

            return fromId(dbData, enumConstants);

        }


        public E fromId(I idValue) {

            return fromId(idValue, enumConstants);

        }


        public static <E extends Enum<E> & PersistableEnum<I>, I> E fromId(I idValue, E[] enumConstants) {

            return Objects.isNull(idValue) ? null : Stream.of(enumConstants)

                                                          .filter(e -> e.getId().equals(idValue))

                                                          .findAny()

                                                          .orElseThrow(() -> new IllegalArgumentException(

                                                              String.format("Does not exist %s with ID: %s", enumConstants[0].getClass().getSimpleName(), idValue)));

        }


    }


    @Converter(autoApply = true)

    class OperationTypeConverter extends AbstractPersistableEnumConverter<OperationType, Integer> {


        public OperationTypeConverter() {

            super(OperationType.class);

        }


    }


}


查看完整回答
反對(duì) 回復(fù) 2024-01-28
  • 3 回答
  • 0 關(guān)注
  • 447 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)