Hibenate枚举转换和转换器映射

时间:2017-11-10 14:21:01

标签: java hibernate enums hibernate-mapping postgresql-9.1

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

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;
   }
}

使用这个实体我设置枚举,我希望hibernate存储来自枚举体的代码。 的 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 类逻辑,我可以从枚举体中获取代码或描述。要将代码存储到数据库中,我使用 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 类型值。当我使用2-nd注释时 - 数据库在枚举类中存储枚举名称或者号码。

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>

当我&#39; m使用1-st注释数据库表如下所示:

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

当我&#39; m使用2-nd注释表如下所示:

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

或者像这样:

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

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

3 个答案:

答案 0 :(得分: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;
   }
}

答案 1 :(得分:1)

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

相反,您可以在字段中使用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

答案 2 :(得分:0)

经过长时间的互联网浏览终于我找到了解决方案。感谢Gabriel Axel。他提出创建自己的值类型类,将枚举转换为他的身体价值。

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