On JavaEE environment, I use JPA 2.1 implementation with EclipseLink,
I have some entities that contain enums. So I have created converters for these enumerations.
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 comment the 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 uncomment the 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
Am I declaring the converters in a wrong way ?
Thank you.
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
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>
My guess is that you have intermixed javax.persistence and org.eclipse.persistence.annotations packages.
Using javax.persistence package classes, you may use an empty Converter annotation on the converter class and a Convert annotation on the entity class specifying the converter class.
Just wanted to make the small remark, that the empty @Converter annotation is supported from JPA 2.1 up via EclipseLink 1. You find the used JPA version under project(rightclick)->properties->facets.
Also note that as mentioned above, if you start to add a single class in the persistence.xml you have to add everything.
Wait till they release the patch for your application server.
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
The workaround for now is to store it as a String and have a getter and setter that would do the transform for you like this
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:
@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);
}
来源:https://stackoverflow.com/questions/27574855/registering-converters-in-jpa-2-1-with-eclipselink