JPA2:Enum的ElementCollection与AttributeConverter

时间:2015-09-07 18:38:18

标签: java jpa

我正在尝试将两个概念结合起来:

  • 存储枚举,它与实体的一对多关系(使用@ElementCollection@CollectionTable
  • 不是按字符串或序号保留枚举,而是使用唯一ID(使用@AttributeConverter

他们应该单独工作(从文档判断),但是当我将它们组合起来时,我会在构建过程中遇到错误。

这是实体:

@Entity
@Table(name = "push_tokens")
public class PushTokenDAO implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long idx;

    @ElementCollection(targetClass = NotificationType.class, fetch = FetchType.EAGER)
    @Convert(converter = NotificationTypeConverter.class)
    @CollectionTable(
            name = "notificationtypes_of_tokens",
            joinColumns = @JoinColumn(name = "fk_tokenIdx")
    )
    @Column(name = "notificationType")
    private List<NotificationType> notificationTypes;

    /* ... */

}

这是Enum:

public enum NotificationType {
    NEW_TRANSFER(10),
    DELIVERY_REPORT(20),
    UPLOAD_CONFIRMATION(30),
    EXPIRY_WARNING(40);

    private final int code;

    NotificationType(int code) {
        this.code = code;
    }

    public static NotificationType parse(int code) {
        for (NotificationType t : NotificationType.values()) {
            if (t.code == code) {
                return t;
            }
        }
        throw new IllegalArgumentException("No such NotificationType");
    }

    public int getCode() {
        return code;
    }
}

转换器:

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

@Converter(autoApply = true)
public class NotificationTypeConverter implements AttributeConverter<NotificationType, Integer> {

    @Override
    public Integer convertToDatabaseColumn(NotificationType x) {
        return x.getCode();
    }

    @Override
    public NotificationType convertToEntityAttribute(Integer y) {
        return NotificationType.parse(y);
    }

}

集合表notificationtypes_of_tokens中只包含两个数字列:

CREATE TABLE `notificationtypes_of_tokens` (
  `fk_tokenIdx` bigint(11) unsigned NOT NULL,
  `notificationType` int(11) unsigned NOT NULL,
  PRIMARY KEY (`fk_tokenIdx`,`notificationType`),
  KEY `fk_tokenIdx` (`fk_tokenIdx`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

问题发生在EclipseLink的静态编织期间,这是构建过程的一部分:

Failed to execute goal de.empulse.eclipselink:staticweave-maven-plugin:1.0.0:weave (default) 
on project skp-server: Execution default of goal de.empulse.eclipselink:staticweave-maven-plugin:1.0.0:weave 
failed: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):
    org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [skp-server-PU] failed.
Internal Exception: Exception [EclipseLink-7351] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):
    org.eclipse.persistence.exceptions.ValidationException
Exception Description: The converter class [com.skalio.skaliopush.db.NotificationTypeConverter] 
    specified on the mapping attribute [notificationTypes] from the class 
    [com.skalio.skaliopush.db.entity.PushTokenDAO] was not found. Please ensure the converter 
    class name is correct and exists with the persistence unit definition.

如果我没有专门引用实体中的转换器(省略@Convert),则转换不会完成;枚举映射到它的序数。这不是我想要的。

仅供参考:代码在Java SE VM上运行,而不是在应用程序服务器上运行。我必须在persistence.xml中指定每个实体类。

1 个答案:

答案 0 :(得分:0)

该解决方案与@ElementCollection,枚举或与@AttributeConverter的组合无关。

相反,答案在于问题what has to be specified in persistence.xml when running on Java SE。错误消息也是以这种方式提示('转换器未找到......')。

persistence.xml中指定转换器类后,编织工作正常,代码构建,并按预期运行。总结:根据上面的代码,将@ElementCollection,Enum和@AttributeConverter合并得很好。