我正在尝试将grails-project转换为playframework。在Grails中,您可以定义一个id,以便将id存储在数据库中(请参阅release notes中的增强的枚举支持)。 我看到similar question,但没有可接受的解决方案。如果我更改CRUD模块的类型会出现问题,因为应该显示Enum的信息会丢失。
所以我想知道是否存在一个很好的解决方案,它基于Hibernate。也许是在破解JPAPlugin?
[更新1]我开始尝试使用@type
- 注释的第二个解决方案。不幸的是,这已经被hibernate 3.6(播放1.2.2使用)破坏了。 TypeFactory.basic()
不再是available。但是根据文档我无法找到解决方法。
[更新2] hibernate 3.6.1有solution,但在每次使用枚举时定义类型真的很笨拙。
@Type(type="hibernatehelper.GenericEnumUserType",
parameters= {
@Parameter(
name = "enumClass",
value = "models.Geschlecht"),
})
public Geschlecht geschlecht = Geschlecht.WEIBLICH;
答案 0 :(得分:4)
不确定它是否真的有效,但可能的解决办法如下:
写了一个泛型类型映射器:
package hibernatehelper;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
import org.hibernate.type.TypeResolver;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
public class GenericEnumUserType implements UserType, ParameterizedType {
private Class <? extends Enum> enumClass;
private Class <?> identifierType;
private Method identifierMethod;
private Method valueOfMethod;
private static final String defaultIdentifierMethodName = "getId";
private static final String defaultValueOfMethodName = "parseId";
private AbstractSingleColumnStandardBasicType type;
private int[] sqlTypes;
@Override
public void setParameterValues(Properties parameters) {
String enumClassName = parameters.getProperty("enumClass");
try {
enumClass = Class.forName(enumClassName).asSubclass(Enum.class);
} catch (ClassNotFoundException exception) {
throw new HibernateException("Enum class not found", exception);
}
String identifierMethodName =
parameters.getProperty("identifierMethod",
defaultIdentifierMethodName);
try {
identifierMethod =
enumClass.getMethod(identifierMethodName, new Class[0]);
identifierType = identifierMethod.getReturnType();
} catch (Exception exception) {
throw new HibernateException("Failed to optain identifier method",
exception);
}
TypeResolver tr = new TypeResolver();
type =
(AbstractSingleColumnStandardBasicType) tr.basic(identifierType
.getName());
if (type == null) {
throw new HibernateException("Unsupported identifier type "
+ identifierType.getName());
}
sqlTypes = new int[] {type.sqlType()};
String valueOfMethodName = parameters.getProperty("valueOfMethod",
defaultValueOfMethodName);
try {
valueOfMethod = enumClass.getMethod(valueOfMethodName,
new Class[] {identifierType});
} catch (Exception exception) {
throw new HibernateException("Failed to optain valueOf method",
exception);
}
}
@Override
public Class returnedClass() {
return enumClass;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
throws HibernateException, SQLException {
Object identifier = type.get(rs, names[0]);
if (identifier == null) {
return null;
}
if (valueOfMethod == null) {
}
try {
return valueOfMethod.invoke(enumClass, new Object[] {identifier});
} catch (Exception exception) {
throw new HibernateException(
"Exception while invoking valueOfMethod of enumeration class: ",
exception);
}
}
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws HibernateException, SQLException {
try {
Object identifier =
value != null ? identifierMethod.invoke(value,
new Object[0]) : null;
st.setObject(index, identifier);
} catch (Exception exception) {
throw new HibernateException(
"Exception while invoking identifierMethod of enumeration class: ",
exception);
}
}
@Override
public int[] sqlTypes() {
return sqlTypes;
}
@Override
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return x == y;
}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
public boolean isMutable() {
return false;
}
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return original;
}
}
编写了一个Enhancer,它查找来自类型Enum
的每个属性,并查看此类型是否具有静态方法parseId。比add the following annotation with javaassist:
@Type(type="hibernatehelper.GenericEnumUserType",
parameters= {
@Parameter(
name = "enumClass",
value = "<fullqualified classname of the enum class>"),
})
但我不确定这对于这样的问题是否有多大的魔力。也许有人可以给我一个建议。