如何在play中存储具有固定值的枚举类型

9 浏览
0 Comments

如何在play中存储具有固定值的枚举类型

我正在试图将一个Grails项目转换为Play框架。在Grails中,你可以定义一个id,这样id就会被存储在数据库中(请参阅发布说明中的增强枚举支持)。\n我看到了一个类似的问题,但没有可接受的解决方案。如果我改变类型,CRUD模块会出现问题,因为丢失了一个应该显示的枚举信息。\n所以我想知道在基于Hibernate的Play中是否存在一个好的解决方案。也许通过修改JPAPlugin来实现?\n[更新1]我开始尝试第二种解决方案,使用@type注解。不幸的是,这在hibernate 3.6(play 1.2.2使用的版本)中出现了问题。 TypeFactory.basic()不再可用。但是根据文档,我找不到解决方法。\n[更新2]对于hibernate 3.6.1有一个解决方案,但在每次使用枚举时定义类型非常笨拙。\n

@Type(type="hibernatehelper.GenericEnumUserType", 
            parameters= {
            @Parameter(
                    name  = "enumClass",                      
                    value = "models.Geschlecht"),
        })
public Geschlecht geschlecht = Geschlecht.WEIBLICH; 

0
0 Comments

在Play框架中,有一个问题是如何存储具有固定值的枚举。以下是可能的解决方法:

1. 编写一个通用的类型映射器。代码如下:

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  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;
    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);
        }
    }
    public Class returnedClass() {
        return enumClass;
    }
    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);
        }
    }
    public int[] sqlTypes() {
        return sqlTypes;
    }
    public Object assemble(Serializable cached, Object owner)
            throws HibernateException {
        return cached;
    }
    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }
    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }
    public boolean equals(Object x, Object y) throws HibernateException {
        return x == y;
    }
    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;
    }
}

2. 编写一个增强器(Enhancer),该增强器查找每个属性,如果属性的类型是Enum,并且该类型有一个名为parseId的静态方法,则使用Javaassist工具为该属性添加注解。代码如下:

(type="hibernatehelper.GenericEnumUserType", 
    parameters= {
    (
            name  = "enumClass",                      
            value = "<完整的枚举类名>"),
})

然而,这种方法可能对于这样的问题来说有点复杂。也许有人可以给我一些建议。

但是,在Spring Boot 2的JAR文件中,上述方法无法生效。是否有其他方法可以使用枚举的顺序(ordinal)来解决这个问题?

0