是否可以为 JPA 编写通用枚举转换器? [英] Is it possible to write a generic enum converter for JPA?

查看:24
本文介绍了是否可以为 JPA 编写通用枚举转换器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为 JPA 编写一个转换器,将任何枚举存储为大写.我们遇到的一些枚举尚未遵循仅使用大写字母的约定,因此在重构之前我仍然存储未来值.

I wanted to write a Converter for JPA that stores any enum as UPPERCASE. Some enums we encounter do not follow yet the convention to use only Uppercase letters so until they are refactored I still store the future value.

到目前为止我得到了什么:

What I got so far:

package student;

public enum StudentState {

    Started,
    Mentoring,
    Repeating,
    STUPID,
    GENIUS;
}

我希望将Started"存储为STARTED"等.

I want "Started" to be stored as "STARTED" and so on.

package student;

import jpa.EnumUppercaseConverter;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

@Entity
@Table(name = "STUDENTS")
public class Student implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long mId;

    @Column(name = "LAST_NAME", length = 35)
    private String mLastName;

    @Column(name = "FIRST_NAME", nullable = false, length = 35)
    private String mFirstName;

    @Column(name = "BIRTH_DATE", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date mBirthDate;

    @Column(name = "STUDENT_STATE")
    @Enumerated(EnumType.STRING)
    @Convert(converter = EnumUppercaseConverter.class)
    private StudentState studentState;

}

转换器目前看起来像这样:

the converter currently looks like this:

package jpa;


import javax.persistence.AttributeConverter;
import java.util.EnumSet;

public class EnumUppercaseConverter<E extends Enum<E>> implements AttributeConverter<E, String> {

    private Class<E> enumClass;

    @Override
    public String convertToDatabaseColumn(E e) {
        return e.name().toUpperCase();
    }

    @Override
    public E convertToEntityAttribute(String s) {
        // which enum is it?
        for (E en : EnumSet.allOf(enumClass)) {
            if (en.name().equalsIgnoreCase(s)) {
                return en;
            }
        }
        return null;
    }

}

不起作用的是我不知道 enumClass 在运行时会是什么.而且我无法找到一种方法将这些信息传递给@Converter 注释中的转换器.

what will not work is that I do not know what enumClass will be at runtime. And I could not figure out a way to pass this information to the converter in the @Converter annotation.

那么有没有办法向转换器添加参数或作弊呢?或者还有其他方法吗?

So is there a way to add parameters to the converter or cheat a bit? Or is there another way?

我使用的是 EclipseLink 2.4.2

I'm using EclipseLink 2.4.2

谢谢!

推荐答案

您需要做的是编写一个通用基类,然后为您想要持久化的每个枚举类型扩展它.然后使用@Converter注解中的扩展类型:

What you need to do is write a generic base class and then extend that for each enum type you want to persist. Then use the extended type in the @Converter annotation:

public abstract class GenericEnumUppercaseConverter<E extends Enum<E>> implements AttributeConverter<E, String> {
    ...
}

public FooConverter
    extends GenericEnumUppercaseConverter<Foo> 
    implements AttributeConverter<Foo, String> // See Bug HHH-8854
{
    public FooConverter() {
        super(Foo.class);
    }
}

其中 Foo 是您要处理的枚举.

where Foo is the enum you want to handle.

另一种方法是定义自定义注释,修补 JPA 提供程序以识别此注释.这样,您就可以在构建映射信息时检查字段类型,并将必要的枚举类型提供给一个纯粹的通用转换器.

The alternative would be to define a custom annotation, patch the JPA provider to recognize this annotation. That way, you could examine the field type as you build the mapping information and feed the necessary enum type into a purely generic converter.

相关:

这篇关于是否可以为 JPA 编写通用枚举转换器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆