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
Registering Converters in JPA 2.1 with EclipseLink
提问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>
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
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
当我在persistence.xml 文件上评论转换器的声明,并尝试将我的实体持久保存在数据库中时,我收到此错误:“请确保转换器类名称正确并且与持久性单元定义一起存在。”。并且没有编译时异常,只有一个非常明确的警告:
类“com.xyz.model.converters.CarTypeConverter”有注释,但未在persistence.xml文件中列出
但是,当我取消对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.persistence和org.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);
}

