In an very distilled version of the sample code available from a tutorial, Embedded Compound Primary Key : Primary Key « JPA « Java Tutorial, I'm getting:
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]
The exception is fairly generic, but Hibernate provides some good log debug info (I've replaced the actual package name with <package>):
[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
Here's the distilled code. (The backstory is that I'd been trying, to no avail, to create an entity with an embedded id. After a while of trying to debug that, I re-started with this tutorial code, removing things until I got the same error.)
@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); }
}
The embeddable class needs to be serializable. Updating the definition of StudentId to implement Serializable (and adding a serialVersionUID), the issue seems to disappear:
@Embeddable
class StudentId implements Serializable {
private static final long serialVersionUID = -7415410969017941320L;
// ...
}
Once I discovered this, I was able to do a bit more research, but it was of varying degrees of helpfulness. For instance, 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?, is more relevant, but making the id class non-serializable there produces a different error message than what I was getting.
User OndrejM, in a comment, 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, is:
2.4 Primary Keys and Entity Identity
… The following rules apply for composite primary keys: …
- The primary key class must be serializable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With