当前位置: 首页 > 面试题库 >

是否可以为JPA编写通用枚举转换器?

宗政金鹏
2023-03-14
问题内容

我想为JPA编写一个Converter,将任何枚举存储为大写。我们遇到的一些枚举还没有遵循惯例,只能使用大写字母,因此在重构它们之前,我仍然会存储将来的值。

我到目前为止所得到的:

package student;

public enum StudentState {

    Started,
    Mentoring,
    Repeating,
    STUPID,
    GENIUS;
}

我希望将“开始”存储为“开始”,依此类推。

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;

}

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

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批注中将此信息传递给转换器的方法。

那么有没有办法向转换器添加参数或作弊呢?还是有另一种方法?

我正在使用EclipseLink 2.4.2

谢谢!


问题答案:

您需要做的是编写一个通用基类,然后将其扩展为要保留的每种枚举类型。然后在@Converter注释中使用扩展类型:

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您要处理的枚举在哪里。

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

有关:

  • https://hibernate.atlassian.net/browse/HHH-8854


 类似资料:
  • 问题内容: 问题是:编写一个交换两个变量的方法。这两个变量应该是原语。它不需要是通用的,例如两个变量。有办法吗? 问题答案: 如果不使用数组或对象,不可以,无法在方法中进行操作。

  • 问题内容: 在Java中有可能发生这种情况吗?可以为Java中的枚举元素分配自定义数值吗? 问题答案:

  • 从这个问题,有可能注入map与枚举? 例如,我有枚举: 我有一些与实现的接口: 但这样的注入不起作用: 我想自动注入。如何修复它,在spring框架端生成这样的代码?

  • 我刚刚注意到javadoc状态(强调为我的): 返回声明中包含的此枚举常量的名称。该方法可能被重写,尽管它通常不是必需的或不需要的。当存在更“程序员友好”的字符串窗体时,枚举类型应重写此方法。 默认情况下,和返回相同的内容,因此即使被重写,仍然可以通过方法访问枚举的名称。 编辑:供参考,的javadoc(强调与原文相同): 返回此枚举常量的名称,与在其枚举声明中声明的名称完全相同。大多数程序员应该

  • 问题内容: 给定以下枚举,将Int强制转换为Java中的枚举的正确方法是什么? 问题答案: 尝试在必须为or的地方,即该枚举的有效序数。 请注意,在Java中,枚举实际上是类(因此,枚举值是对象),因此您不能将an 甚至转换为枚举。