JPA Hibernate null pointer exception with OneToOne primary key/foreign key type relation

不问归期 提交于 2019-12-11 16:08:28

问题


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:

  1. IdType.code is in its own separate table because I wanted to isolate Person from IdDescription (from a Java structure perspective)
  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!