Java 将枚举映射到具有hibernate注释的表
我有桌上交易和桌上交易类型。我想映射此代码:Java 将枚举映射到具有hibernate注释的表,java,hibernate,enums,orm,Java,Hibernate,Enums,Orm,我有桌上交易和桌上交易类型。我想映射此代码: public class Deal { DealType type; } public enum DealType { BASE("Base"), EXTRA("Extra"); } 问题是数据库中已经存在数据。我很难将这些类映射到数据库 数据库看起来像这样: TABLE DEAL { Long id; Long typeId; } TABLE DEAL_TYPE { Long
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开始的
有什么建议吗?Hibernate在枚举中有点糟糕。这是一个很好的ORM的奇怪的失败。绕过它的“最简单”方法是将枚举声明为自定义hibernate类型。幸运的是,Hibernate编写了一个示例实现,您可以将逐字记录到应用程序中:
它们甚至包括如何使用它的说明。这就是我在需要持久化枚举时使用的模式 虽然远不理想,但我对这个问题的解决方案是使用EnumStringType和非规范化的可更新视图。我创建了一个类似于hibernate建议的类,它是可配置的,并且不需要为这个持久性创建新类型 可以像这样使用
@Type(type = "ro.raisercostin.hibernate.EnumUserType", parameters = @Parameter(name = "type", value = "DealType"))
DealType dealType;
我添加了ParameteredType的实现来支持传递的参数
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
enum声明如下所示:
@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();
}
};
}
}
如果要使用只读实体,则可以使用
@公式
和@枚举
。尝试以下方法:
@Entity
public class Deal {
@Formula("(select text from DEAL_TYPE dt where dt.id = typeId)")
@Enumerated(EnumType.STRING)
DealType type;
}
是的,我一直不明白为什么他们没有更好的解决方案。但是你在哪里定义枚举的id列和文本列?我不明白如何将枚举映射到一个单独的带有id和描述的表。您能否给出一个代码示例,说明如何在Hibernate注释中实现这一点?这是@Naor提出的问题。这个答案已经过时了,我们现在可以使用它了,似乎Hibernate在两个方法上扩展了签名,但在其他方面,这对我来说很好。有没有想过把它贡献给Hibernate项目?@raisercostin,我正在尝试你上面解释的东西。我不确定注释中的参数值是什么。请你详细说明一下,或者指出我可以获得更多信息的来源。现在我明白了。参数类似于type:DealType,其中type是使用的键EnumUserType,value是类(使用完整的类名,包括包)。我认为现在可以使用@Enumeratedyou's life saver来摆脱Tuplizer。有了这个,我可以将hibernate对象恢复为带有自定义值的枚举,并在repositories中使用它们,这不是一个糟糕的解决方案,因为您也考虑过插入和更新。这里的其他一些解决方案可能只是为了阅读。虽然这只适用于少数数据库,如Oracle。虽然我在MSSQL上实现了这一点,可更新视图非常简单,但在大多数RDBMS系统上通过在视图上放置“而不是”触发器来修改基础表,应该可以进行模拟。