Hibernate 枚举转换和转换器映射

Hibernate enum casting and converter mapping

我正在使用枚举,我想将枚举体中的代码存储在数据库中。我正在使用 hibernate 5.2.11.. 对于实体​​映射,我正在使用 .hbm.xml 文件。我做错了什么?为什么我不能存储 enmus 代码。它一直存储枚举名称或字节数组。

MyEntity.java

    public class MyEntity {

       private Long id;
       private MyEnums num;

       public Long getId() {
           return id;
       }

       public void setId(Long id) {
           this.id = id;
       }

       @Convert(converter = MyEnumConverter.class)
       public MyEnums getNum() {
           return num;
       }

       @Convert(converter = MyEnumConverter.class)
       public void setNum(MyEnums num) {
           this.num = num;
       }
    }

使用这个实体我正在设置枚举并且我希望休眠存储枚举体中的代码。 MyEnums.java

    public enum MyEnums {

       FIRST("123", "first"),
       SECOND("456", "second");

       private final String code;
       private final String description;

       private MyEnums(String code, String description) {
           this.code = code;
           this.description = description;
       }

       public static MyEnums fromCode(String code) {
           if (code.equals(FIRST.code)) {
               return FIRST;
           } else if (code.equals(SECOND.code)) {
               return SECOND;
           } else {
               return null;
           }
       }

       public String getCode() {
           return code;
       }

       public String getDescription() {
           return description;
       }
    }

使用 MyEnums class 逻辑我可以从枚举体中获取代码或描述。为了将代码存储到数据库中,我使用 AttributeConverter<>.

MyEnumConverter.java

    @Converter(autoApply = true)
    public class MyEnumConverter implements AttributeConverter<MyEnums, String> {

       @Override
       public String convertToDatabaseColumn(MyEnums myEnums) {
           return (myEnums != null)? myEnums.getCode() : null;
       }

       @Override
       public MyEnums convertToEntityAttribute(String code) {
           return (code != null)? MyEnums.fromCode(code) : null;
       }
    }

正如我所说,我正在使用 .hbm.xml 映射。所以我尝试了两种不同的方法来映射我的枚举类型。当我使用 1-ST 注释时 - 数据库存储 bytea 类型值。当我使用第二个注释时 - 数据库在枚举 class.

中存储枚举名称或职位编号

MyEntity.hbm.xml

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

    <hibernate-mapping>
        <class name="main.test.main.MyEntity" table="test_enums">
            <id name="id" column="id">
                <generator class="org.hibernate.id.enhanced.SequenceStyleGenerator">
                    <param name="optimizer">none</param>
                    <param name="increment_size">1</param>
                    <param name="sequence_name">seq_enums</param>
                </generator>
            </id>

       <!-- 1-ST ANNOTATION -->
            <property name="num" column="enum_code"/>

       <!-- 2-ND ANNOTATION -->
            <!--<property name="num" column="enum_code">
                <type name="org.hibernate.type.EnumType">
                    <param name="enumClass">main.test.main.MyEnums</param>
                </type>
            </property>-->
        </class>
    </hibernate-mapping>

当我使用 1-st 注释数据库时 table 看起来像这样:

----------------------------------
| id | enum_code                 |
----------------------------------
| 1  | 81B 00000000 AC ED 00 ... |
----------------------------------

当我使用第二个注释时 table 看起来像这样:

----------------------------------
| id | enum_code                 |
----------------------------------
| 1  | SECOND                    |
----------------------------------

或者像这样:

----------------------------------
| id | enum_code                 |
----------------------------------
| 1  | 1                         |
----------------------------------

看来我的枚举转换器不起作用。有人遇到过这类问题吗?我真的需要一些帮助...

我认为hibernate正在考虑字段而忽略了getter/setter,尝试注释字段...

public class MyEntity {

   private Long id;
   @Convert(converter = MyEnumConverter.class)
   private MyEnums num;

   public Long getId() {
       return id;
   }

   public void setId(Long id) {
       this.id = id;
   }

   public MyEnums getNum() {
       return num;
   }

   public void setNum(MyEnums num) {
       this.num = num;
   }
}

我认为问题出在您的转换器 @Converter 中使用 autoApply = true,它将始终被应用。

相反,您可以在您的字段中使用 Enumerated,有两个选项:

EnumType.ORDINAL:

<property name="num" column="enum_code">
    <type name="org.hibernate.type.EnumType">
        <param name="enumClass">main.test.main.MyEnums</param>
    </type>
</property>

EnumType.STRING

<property name="num" column="enum_code">
    <type name="org.hibernate.type.EnumType">
        <param name="enumClass">main.test.main.MyEnums</param>
        <param name="useNamed">true</param>
    </type>
</property>

如需更多详细信息,您可以查看 Hibernate Enum Type Mapping Example

经过长时间的互联网浏览,终于我找到了解决方案。感谢加布里埃尔·阿克塞尔。他提议创建您自己的值类型 class,将枚举转换为他的正文值。

更多信息(示例):http://www.gabiaxel.com/2011/01/better-enum-mapping-with-hibernate.html