问题
I'm having lots of trouble with a little prototype I'm trying to build.
The problem involves two entities. But to understand it, I will need to describe a few others.
In terms of the database structure, it can be described as follows:
Person
----------------
id Integer PK
surname VARCHAR
givenNames VARCHAR
TypedIdentifier
----------------
idCode VARCHAR PK FK (IdType.code)
idVal VARCHAR PK
person Integer FK (Person.id)
IdType
------
code VARCHAR PK
IdDescription
----------
code VARCHAR PK FK (IdType.code)
category VARCHAR
name VARCHAR
My problem appears in the relationship between tables IdDescription and IdType.
Basically, the IdType table should consist of a single column, that being the primary key (unique) and the secondary table (IdDescription), which describes the id-type, should have a foreign key to that column.
Two important points which guided my design of the database:
- IdType.code is in its own separate table because I wanted to isolate Person from IdDescription (from a Java structure perspective)
- Because both tables TypedIdentifier and IdDescription need to reference IdType, I can only have references/relationship annotations to IdType in THOSE tables (and none in IdType itself).
My Java code looks like this:
Person
@MappedSuperclass
public class Person implements Serializable
{
/**
* internal unique identifier
*/
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public Integer id;
/**
*
* Assigned patient identifiers
*/
@OneToMany(targetEntity=TypedIdentifier.class, mappedBy="ownerPerson", fetch=FetchType.EAGER)
public List<TypedIdentifier> patientIdentifiers;
/**
* natural identifiers
*/
public String surname;
public String givenNames;
}
TypedIdentifier
@Table(uniqueConstraints = @UniqueConstraint(columnNames={"idType", "idValue"}))
@Entity @IdClass(TypedIdentifier.class)
public class TypedIdentifier implements Serializable
{
/**
* internal unique identifier
*/
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public Integer id;
@Id
@ManyToOne(fetch=FetchType.LAZY)
public IdType idType; // should be a foreign key
@Id
public String idValue;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn
public Person ownerPerson;
}
IdType
@Entity
public class IdType implements Serializable
{
@Id
public String code;
}
IdTypeDescription
@Entity
public class IdTypeDescription implements Serializable
{
@MapsId
@JoinColumn(name = "code")
@OneToOne(cascade = CascadeType.ALL, mappedBy="code")
public IdType itype;
public IdCategory category;
public String name;
}
If I needed to write this up in SQL I would have no problems. But with JPA/Hibernate a simple thing is turning into a nightmare. I'm bouncing from one error to another and back again.
My problem seems to come from my annotation of the itype member of IdTypeDescription. I've tried various ways (based on example code and API documentation).
These annotation combinations result in my metamodel generator not generating attributes for my static class IdTypeDescription_
@MapsId
@JoinColumn(name = "code")
@OneToOne(cascade = CascadeType.ALL, mappedBy="code")
public IdType itype;
These annotation combinations result in a null pointer exception in hibernate as it attempts to create the tables:
@Id
@OneToOne(cascade = CascadeType.ALL, mappedBy="code")
public IdType itype;
or
@Id
@OneToOne(cascade = CascadeType.ALL, mappedBy="code")
@PrimaryKeyJoinColumn
public IdType itype;
Errors:
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, javax.persistence.PersistenceException: Unable to build entity manager factory
at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:35)
at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:30)
while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
while locating play.db.jpa.JPAApi
1 error]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:265) ~[play_2.11-2.4.4.jar:2.4.4]
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:191) ~[play_2.11-2.4.4.jar:2.4.4]
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [scala-library-2.11.6.jar:na]
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [scala-library-2.11.6.jar:na]
Caused by: com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, javax.persistence.PersistenceException: Unable to build entity manager factory
at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:35)
at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:30)
while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
while locating play.db.jpa.JPAApi
1 error
at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1025) ~[guice-4.0.jar:na]
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051) ~[guice-4.0.jar:na]
at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:1016) ~[guice-4.0.jar:na]
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1092) ~[guice-4.0.jar:na]
at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1012) ~[guice-4.0.jar:na]
... 38 common frames omitted
Caused by: java.lang.NullPointerException: null
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processFkSecondPassesInOrder(InFlightMetadataCollectorImpl.java:1708) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1617) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:278) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:770) ~[hibernate-entitymanager-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:797) ~[hibernate-entitymanager-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58) ~[hibernate-entitymanager-5.0.5.Final.jar:5.0.5.Final]
... 57 common frames omitted
来源:https://stackoverflow.com/questions/35314780/jpa-hibernate-null-pointer-exception-with-onetoone-primary-key-foreign-key-type