如何使用 Hibernate 6.2 将枚举列表映射到 Varchar

问题描述 投票:0回答:1

我目前正在尝试创建一个自定义 Hibernate 类型,以将枚举列表映射到逗号分隔元素的 Varchar 中。为此,我编写了自己的 JavaType(旧 JavaTypeDescriptor)和自己的 BasicType。问题是,对于我的第二堂课,我需要一个 JavaType 的实例。

尝试1

在 Hibernate 5 中,可以在需要时设置 JavaType,使用参数注释并在其中设置类型(使用

AbstractStandardBasicType#setJavaTypeDescriptor
)。在 Hibernate 6.2 版本中,该方法不再可用,并且 javaTypeDescriptor 字段(现在是 javaType)是最终字段,因此我无法执行此操作。 这是我尝试过的代码:

public class EnumListJavaType<E extends Enum<E>> extends AbstractJavaType<List<E>> {

    private final Class<E> enumClass;

    private static final String SEPARATOR = ",";

    public EnumListJavaType(Class<E> enumClass) {
        super(List.class);
        this.enumClass = enumClass;
    }

    @Override
    public <X> X unwrap(List<E> value, Class<X> type, WrapperOptions options) {
        if (value == null)
            return null;
        return (X) toString(value);
    }

    @Override
    public <X> List<E> wrap(X value, WrapperOptions options) {
        if (value == null)
            return null;
        return fromString(value.toString());
    }

    @Override
    public String toString(List<E> value) {
        return (String) value.stream()
                .map(Enum::name)
                .collect(Collectors.joining(SEPARATOR));
    }

    public List<E> fromString(String string) {
        if (StringUtils.isEmpty(string))
            return null;
        return Arrays.stream(string.split(SEPARATOR))
                .map(s -> Enum.valueOf(enumClass, s))
                .collect(Collectors.toList());
    }
}
public class EnumListType<E extends Enum<E>> extends AbstractSingleColumnStandardBasicType<List<E>> implements DynamicParameterizedType {


    /**
     * Here the JavaType is not passed as we don't know yet the enum class.
     */
    public EnumListType() {
        super(VarcharJdbcType.INSTANCE, null);

    @Override
    public String getName() {
        return "enum_list";
    }

    @Override
    public String[] getRegistrationKeys() {
        return new String[] { getName(), "EnumList", EnumSet.class.getName() };
    }

    @Override
    public void setParameterValues(Properties parameters) {
// Here I'm not able to set the JavaType anymore as there is no such method
/*        String enumClassName = (String) parameters.get("enumClass");

        try {
            setJavaType(new EnumSetJavaType(Class.forName(enumClassName)));
        }
        catch (ClassNotFoundException e) {}*/
    }

我现在看到的唯一方法是删除泛型并将我的 JavaType 定义为列表。但我希望有一种更干净的方法来做到这一点。

尝试2

然后我考虑创建一个工厂,以便在需要时通过使用注释 @TypeDef 来创建 HavaType。类似的东西:

public class EnumListTypeFactory implements TypeDef {

    @Override
    public Class getTypeClass() {
        return EnumListType.class;
    }

    @Override
    public String getTypeMethod() {
        return "forEnumClass";
    }

    public static <E extends Enum<E>> EnumListType forEnumClass(String enumClassName) {
        try {
            Class<E> enumClass = (Class<E>) Class.forName(enumClassName);
            return new EnumListType<>(new EnumListJavaType<>(enumClass));
        } catch (ClassNotFoundException e) {
            throw new HibernateException("Enum class not found", e);
        }
    }

但是在Hibernate 6中,@TypeDef注解似乎已经被删除了。

如果您对此有任何建议,我将不胜感激!

java spring hibernate generics mapping
1个回答
0
投票

如果你真的想要数据库中的 varchar 列,我想你只需要提供

<E extends Enum<E>> AttributeConverter<EnumSet<E>, String>

除了使用

Set
而不是
EnumSet
,我想你可以在这里获取一个实现。

© www.soinside.com 2019 - 2024. All rights reserved.