使用hibernate注释将枚举映射到表

我有一个表DEAL和一个表DEAL_TYPE。 我想映射这段代码:

public class Deal { DealType type; } public enum DealType { BASE("Base"), EXTRA("Extra"); } 

问题是数据已存在于数据库中。 而且我很难将类映射到数据库。

数据库看起来像这样:

  TABLE DEAL { Long id; Long typeId; } TABLE DEAL_TYPE { Long id; String text; } 

我知道我可以使用简单的@OneToMany关系从交易到交易类型,但我更喜欢使用枚举。 这可能吗?

我几乎使用EnumType.ORDINAL类型工作。 但不幸的是,我的交易类型表中的ID不是顺序的,并且不是从1开始。

有什么建议么?

在Enums中,Hibernate有点可怕。 这是一个奇怪的失败,否则相当不错的ORM。 解决它的“最简单”方法是将Enum声明为自定义hibernate类型。 幸运的是,Hibernate编写了一个示例实现,您可以将其逐字记录到您的应用程序中:

http://www.hibernate.org/265.html

它们甚至包括如何使用它的说明。 这是我在最终需要持久化枚举时使用的模式。

我创建了一个类似于hibernate所建议的类,它是可配置的,不需要为这个持久性创建一个新类型。

可以像

 @Type(type = "ro.raisercostin.hibernate.EnumUserType", parameters = @Parameter(name = "type", value = "DealType")) DealType dealType; 

我添加了ParameterizedType的实现来支持传递的参数。

 public class EnumUserType implements UserType, ParameterizedType { private static final int[] SQL_TYPES = { Types.VARCHAR }; private Class clazz = null; public EnumUserType() { } @Override public void setParameterValues(Properties parameters) { String className = (String) parameters.get("type"); try { this.clazz = Class.forName(className); } catch (ClassNotFoundException e) { throw new RuntimeException("Couldn't get the class for name [" + className + "].", e); } } public int[] sqlTypes() { return SQL_TYPES; } public Class returnedClass() { return clazz; } public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException { String name = resultSet.getString(names[0]); Object result = null; if (!resultSet.wasNull()) { result = Enum.valueOf(clazz, name); } return result; } public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException { if (null == value) { preparedStatement.setNull(index, Types.VARCHAR); } else { preparedStatement.setString(index, ((Enum) value).name()); } } public Object deepCopy(Object value) throws HibernateException { return value; } public boolean isMutable() { return false; } public Object assemble(Serializable cached, Object owner) throws HibernateException { return cached; } public Serializable disassemble(Object value) throws HibernateException { return (Serializable) value; } public Object replace(Object original, Object target, Object owner) throws HibernateException { return original; } public int hashCode(Object x) throws HibernateException { return x.hashCode(); } public boolean equals(Object x, Object y) throws HibernateException { if (x == y) { return true; } if ((null == x) || (null == y)) { return false; } return x.equals(y); } } 

您可以使用@Entity注释枚举并使用custoumn tuplizer使用Enum.valueOf创建枚举的实例

然后枚举声明如下:

 @Entity @Table(name = "node_interface_type") @Tuplizer(impl = EnumTuplizer.class) public enum Type { WIRED, WIRELESS, WIRELESS_SENSOR_NODE; @Id public String name = toString(); } 

Tuplizer是:

 public class EnumTuplizer extends PojoEntityTuplizer { public EnumTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { super(entityMetamodel, mappedEntity); } @Override protected Instantiator buildInstantiator(final PersistentClass persistentClass) { return new Instantiator() { @Override public Object instantiate(Serializable id) { try { return Enum.valueOf( (Class) persistentClass.getClass().getClassLoader().loadClass(persistentClass.getClassName()), (String) id ); } catch (ClassNotFoundException e) { throw new AssertionError(e); } } @Override public Object instantiate() { throw new UnsupportedOperationException(); } @Override public boolean isInstance(Object object) { throw new UnsupportedOperationException(); } }; } } 

如果您只想使用只读实体,那么您可以使用@Formula@Enumerated 。 尝试以下方法:

 @Entity public class Deal { @Formula("(select text from DEAL_TYPE dt where dt.id = typeId)") @Enumerated(EnumType.STRING) DealType type; } 

虽然远非理想,但我对此问题的解决方案是使用EnumStringType和非规范化可更新视图。