【问题标题】:Hibernate @Enumerated mappingHibernate @Enumerated 映射
【发布时间】:2011-07-23 23:33:28
【问题描述】:

Hibernate 提供了@Enumerated 注解,它支持使用ORDINALSTRING 两种类型的Enum 映射。当我们使用EnumType.STRING 进行映射时,它采用Enum 的“名称”而不是枚举的toString() 表示。在数据库列仅包含一个字符的情况下,这是一个问题。例如,我有以下枚举:

public enum Status{
  OPEN{
   @Override
   public String toString(){
     return "O";}
   },

  WAITLIST{
   @Override
   public String toString(){
     return "W";}
   },

  COMPLETE{
   @Override
   public String toString(){
     return "C";}
   }

}

当我使用 @Enumerated(EnumType.STRING) 持久化枚举 Status.OPEN 时,Hibernate 尝试存储在数据库中的值是 OPEN。但是,我的数据库列仅包含一个字符,因此会引发异常。

解决此问题的一种方法是更改​​ Enum 类型以保存单个字符(例如 STATUS.OSTATUS.W 而不是 STATUS.OPENSTATUS.WAITLIST)。但是,这会降低可读性。有什么建议可以保持可读性以及将 Enum 映射到单个字符列?

谢谢。

【问题讨论】:

    标签: java hibernate jpa enums


    【解决方案1】:

    为枚举自定义映射的最佳方法是使用AttributeConverter,即:

    @Entity
    public class Person {
        ...
        @Basic
        @Convert( converter=GenderConverter.class )
        public Gender gender;
    }
    
    public enum Gender {
        MALE( 'M' ),
        FEMALE( 'F' );
    
        private final char code;
    
        private Gender(char code) {
            this.code = code;
        }
    
        public char getCode() {
            return code;
        }
    
        public static Gender fromCode(char code) {
            if ( code == 'M' || code == 'm' ) {
                return MALE;
            }
            if ( code == 'F' || code == 'f' ) {
                return FEMALE;
            }
            throw ...
        }
    }
    
    @Converter
    public class GenderConverter
            implements AttributeConverter<Gender, Character> {
    
        public Character convertToDatabaseColumn(Gender value) {
            if ( value == null ) {
                return null;
            }
    
            return value.getCode();
        }
    
        public Gender convertToEntityAttribute(Character value) {
            if ( value == null ) {
                return null;
            }
    
            return Gender.fromCode( value );
        }
    }
    

    您可以在 Hibernate 文档中找到它: http://docs.jboss.org/hibernate/orm/5.0/mappingGuide/en-US/html_single/#d5e678

    【讨论】:

    • 如果您使用的是 Hibernate 5.x 及更高版本,推荐的方法。
    • 不应该反过来吗 - AttributeConverter&lt;Gender, Character&gt;? JavaDoc 说 @param X is the type of the entity attribute; @param Y is the type of the database column.
    • 是的,你是对的,我会在我的回答中更正它。
    【解决方案2】:

    【讨论】:

    • 有没有人使用上述链接中的解决方案并且能够进行枚举映射?我使用的是 Hibernate 3.6.7,但没有 TypeFactory.basic 方法。关于我应该如何前进的任何提示?
    • 文章链接不是正确的答案格式。
    【解决方案3】:

    这是一个使用注解的例子。

    http://www.gabiaxel.com/2011/01/better-enum-mapping-with-hibernate.html

    它仍然基于自定义 UserType。四年半过去了,我仍然不知道有更好的方法来做到这一点。

    通常,我将枚举值保存为 char / int、一些简单 ID,然后使用临时方法通过简单 ID 值找到适当的枚举,例如

    @Transient
    public MyEnum getMyEnum() {
        return MyEnum.findById(simpleId); // 
    }
    

    还有……

    public enum MyEnum {
        FOO('F'),
        BAR('B');
    
        private char id;
        private static Map<Character, MyEnum> myEnumById = new HashMap<Character, MyEnum>();
    
        static {
            for (MyEnum myEnum : values()) {
                myEnumById.put(myEnum.getId(), myEnum);
            }
        }
    
        private MyEnum(char id) {
            this.id = id;
        }
    
        public static MyEnum findById(char id) {
            return myEnumById.get(id);
        }
    
        public char getId() {
            return id;
        }
    }
    

    【讨论】:

      【解决方案4】:
      public enum Status
      {
          OPEN("O"),
          WAITLIST("W"),
          COMPLETE("C")
      
      private String description;
      
      private Status(String description)
      {
         this.description = description;
      }
      
      public String getDescription()
      {
          return description;
      }
      }
      
      and then when you read it:
      
      Status.OPEN.getDescription()
      

      【讨论】:

        猜你喜欢
        • 2018-06-09
        • 1970-01-01
        • 1970-01-01
        • 2011-07-26
        • 2010-11-27
        • 2013-04-25
        • 1970-01-01
        • 1970-01-01
        • 2017-12-05
        相关资源
        最近更新 更多