"Not known whether passed class name ... is safe" 将 JPA EmbeddedId 与 Hibernate 结合使用

"Not known whether passed class name ... is safe" using JPA EmbeddedId with Hibernate

在教程 Embedded Compound Primary Key : Primary Key « JPA « Java Tutorial 提供的示例代码的精炼版本中,我得到:

javax.persistence.PersistenceException: [PersistenceUnit: unit] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:877)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:805)
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
    at [my code that calls e.persist on a Student]

异常是相当通用的,但 Hibernate 提供了一些很好的日志调试信息(我用 替换了实际的包名称):

[DEBUG] org.hibernate.boot.internal.ClassLoaderAccessImpl: Not known whether passed class name [<package>.Student] is safe
[DEBUG] org.hibernate.boot.internal.ClassLoaderAccessImpl: No temp ClassLoader provided; using live ClassLoader for loading potentially unsafe class : <package>.Student

这是经过提炼的代码。 (背景故事是,我一直在尝试创建一个带有嵌入式 ID 的实体,但无济于事。尝试调试了一段时间后,我重新开始使用本教程代码,删除了一些东西,直到出现相同的错误.)

@Embeddable
class StudentId {
    private int id; 

    public StudentId() {}

    public StudentId(int id) { this.id = id; }

    @Override
    public boolean equals(Object o) { 
        return ((o instanceof StudentId) && id == ((StudentId) o).id);
    }

    @Override
    public int hashCode() { return id; }
}

@Entity
public class Student {
    @EmbeddedId
    private StudentId id;

    public Student() {}

    public Student(int id) { this.id = new StudentId(id); }
}

可嵌入的 class 需要可序列化。更新 StudentId 的定义以实现 Serializable(并添加一个 serialVersionUID),问题似乎消失了:

@Embeddable
class StudentId implements Serializable {

    private static final long serialVersionUID = -7415410969017941320L;

    // ...
}

一旦我发现了这一点,我就能够做更多的研究,但它有不同程度的帮助。例如,Do Hibernate table classes need to be Serializable?, discusses whether entity classes need to be Serializable. In general, they don't. Another question, Why composite-id class must implement Serializable? 更相关,但是使 id class 不可序列化会产生与我得到的不同的错误消息。

, pointed out an answer to How to map a composite key with Hibernate? that locates the part of the JPA 1.0 specification that dictates that composite key classes must be serializable. For completeness, the relevant portion from the later spec, JSR-000338 JavaTM Persistence 2.1 Final Release for Evaluation 中的用户 OndrejM 是:

2.4 Primary Keys and Entity Identity

… The following rules apply for composite primary keys: …

  • The primary key class must be serializable.