java 使用 EclipseLink 在 JPA 2.1 中注册转换器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27574855/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 12:02:07  来源:igfitidea点击:

Registering Converters in JPA 2.1 with EclipseLink

javajakarta-eejpaeclipselinkjpa-2.1

提问by thomas.mc.work

On JavaEE environment, I use JPA 2.1 implementation with EclipseLink,

在 JavaEE 环境中,我使用带有 EclipseLink 的 JPA 2.1 实现,

I have some entities that contain enums. So I have created converters for these enumerations.

我有一些包含enums. 所以我为这些枚举创建了转换器。

Car entity :

汽车实体:

@Entity
public class Car implements Serializable {

    private static final long serialVersionUID = 6L;

    @Id
    private String      id;

    @Convert (converter = CarColorConverter.class)
    private CarColor    color;

    public enum CarColor {
        Black,
        Gray,
        White,
        Red
    };

    public Car () {
        id = GenerateUUID.id ();
    }

    ....
}

CarColor Converter :

汽车颜色转换器:

@Converter (converterClass = CarColorConverter.class, name = "CarColorConverter") 
public class CarColorConverter implements AttributeConverter<CarColor, String> { 

    private static final String BLACK   = "Black";
    private static final String GRAY    = "Gray";
    private static final String WHITE   = "White";
    private static final String RED     = "Red";

    @Override
    public String convertToDatabaseColumn (CarColor entityData) {

        switch (entityData) {
            case Black:
                return BLACK;

            case Gray:
                return GRAY;

            case White:
                return WHITE;

            case Red:
                return RED;

            default:
                throw new IllegalArgumentException ("Unknown : " + entityData);
        }
    }

    @Override
    public CarColor convertToEntityAttribute (String dbData) {

        switch (dbData) {
            case BLACK:
                return CarColor.Black;

            case GRAY:
                return CarColor.Gray;

            case WHITE:
                return CarColor.White;

            case RED:
                return CarColor.Red;

            default:
                throw new IllegalArgumentException ("Unknown : " + dbData);
        }
    }
}

persistence.xml

持久化文件

<?xml version="1.0" encoding="UTF-8"?>
<persistence 
    version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">

    <persistence-unit name="xyz-restful-api" transaction-type="RESOURCE_LOCAL">

        <!-- Converters -->
        <!--<class>com.xyz.model.converters.CarColorConverter</class>-->

        <!-- Entities / Model -->
        <class>com.xtz.model.Car</class>

        <properties>
            ...
        </properties>

    </persistence-unit>

</persistence>
  1. When I commentthe declaration of the converter on the persistence.xml file, and try to persist my entities in the DB I get this error : "Please ensure the converter class name is correct and exists with the persistence unit definition.". and no compilation time exception, only a warning pretty explicit :

    Class "com.xyz.model.converters.CarTypeConverter" is annotated, but not listed in the persistence.xml file

  2. However, when I uncommentthe declaration of the converter on the on the persistence.xml file, and try to persist my entities in the DB I get this error : "Please ensure the converter class name is correct and exists with the persistence unit definition.". and a compilation time exception :

    Class "com.xyz.model.converters.CarColorConverter" is listed in the persistence.xml file, but is not annotated

  1. 在persistence.xml 文件上评论转换器的声明,并尝试将我的实体持久保存在数据库中时,我收到此错误:“请确保转换器类名称正确并且与持久性单元定义一起存在。”。并且没有编译时异常,只有一个非常明确的警告:

    类“com.xyz.model.converters.CarTypeConverter”有注释,但未在persistence.xml文件中列出

  2. 但是,当我取消对persistence.xml 文件上的转换器声明的注释,并尝试将我的实体保留在数据库中时,我收到此错误:“请确保转换器类名称正确并且存在于持久性单元定义中。”。和编译时异常:

    类“com.xyz.model.converters.CarColorConverter”列在persistence.xml文件中,但没有注释

Am I declaring the converters in a wrong way ?

我是否以错误的方式声明转换器?

Thank you.

谢谢你。

回答by thomas.mc.work

Give this a try and ensure you have included the correct packages.

试一试并确保您包含了正确的包。

Car entity

汽车实体

Stays the same

保持不变

import javax.persistence.Convert;

@Entity
public class Car implements Serializable {

    [...]

    @Convert(converter = CarColorConverter.class)
    private CarColor    color;

    [...]
}

CarColor Converter

汽车颜色转换器

You only need the empty Annotation

你只需要空的 Annotation

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter
public class CarColorConverter implements AttributeConverter<CarColor, String> {
    [...]
}

persistence.xml

持久化文件

You can either

你可以要么

  • declare no class at all
  • 根本不声明任何类

or

或者

  • declare every class that is involved.
  • 声明涉及的每个类。

As soon as you need to declare an entity manually (e.g. when it resists in a library) then you also need do declare all other entity/converter classes.

一旦您需要手动声明实体(例如,当它在库中抵抗时),那么您还需要声明所有其他实体/转换器类。

<?xml version="1.0" encoding="UTF-8"?>
<persistence 
    version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">

    <persistence-unit name="xyz-restful-api" transaction-type="RESOURCE_LOCAL">

        <!-- Converters -->
        <class>com.xyz.model.converters.CarColorConverter</class>

        <!-- Entities / Model -->
        <class>com.xtz.model.Car</class>

        [...]
    </persistence-unit>
</persistence>

回答by Petros Splinakis

My guess is that you have intermixed javax.persistenceand org.eclipse.persistence.annotationspackages.

我的猜测是你混合了javax.persistenceorg.eclipse.persistence.annotations包。

Using javax.persistencepackage classes, you may use an empty Converterannotation on the converter class and a Convertannotation on the entity class specifying the converter class.

使用javax.persistence包类,您可以Converter在转换器类上使用空Convert注释,在实体类上使用指定转换器类的注释。

回答by Frank Essenberger

Just wanted to make the small remark, that the empty @Converterannotation is supported from JPA 2.1 up via EclipseLink 1. You find the used JPA version under project(rightclick)->properties->facets.

只是想说一下,@Converter从 JPA 2.1 开始,通过 EclipseLink 1支持空注释。您可以在项目(右键单击)-> 属性-> 构面下找到使用的 JPA 版本。

Also note that as mentioned above, if you start to add a single class in the persistence.xmlyou have to add everything.

另请注意,如上所述,如果您开始在 中添加单个类,则persistence.xml必须添加所有内容。

回答by Archimedes Trajano

Wait till they release the patch for your application server.

等到他们为您的应用程序服务器发布补丁。

https://bugs.eclipse.org/bugs/show_bug.cgi?id=443546

https://bugs.eclipse.org/bugs/show_bug.cgi?id=443546

The release schedules pending are listed in http://www-01.ibm.com/support/docview.wss?uid=swg27004980

http://www-01.ibm.com/support/docview.wss?uid=swg27004980中列出了待定的发布时间表

The workaround for now is to store it as a Stringand have a getter and setter that would do the transform for you like this

现在的解决方法是将其存储为 aString并有一个 getter 和 setter 可以像这样为您进行转换

public final class StaticEnumToStringConverter {

    public static <E extends Enum<E>> String convertToDatabaseColumn(final E attribute) {

        if (attribute == null) {
            return null;
        }
        return attribute.toString();
    }

    public static <E extends Enum<E>> E convertToEntityAttribute(final String dbData, final Class<E> enumClass) {

        if (dbData == null) {
            return null;
        }
        for (final E c : EnumSet.allOf(enumClass)) {
            if (dbData.equals(c.toString())) {
                return c;
            }
        }
        throw new IllegalArgumentException(dbData);

    }

    private StaticEnumToStringConverter() {

    }
}

Then use in the JPA Entity as:

然后在 JPA 实体中使用:

@NotNull
@Column(nullable = false)
private String genderAtBirth;

public Gender getGenderAtBirth() {
    return StaticEnumToStringConverter.convertToEntityAttribute(genderAtBirth, Gender.class);
}
public void setGenderAtBirth(final Gender genderAtBirth) {

    this.genderAtBirth = StaticEnumToStringConverter.convertToDatabaseColumn(genderAtBirth);
}