我正在尝试构建一个小原型,我遇到了很多麻烦。
问题涉及两个实体。但要理解它,我需要描述其他一些。
就数据库结构而言,可以描述如下:
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
我的问题出现在表IdDescription和IdType 之间的 关系中。
基本上,IdType表应该包含一个列,即主键(唯一)和辅助表(IdDescription),它描述了id-type,应该有一个该列的外键。
指导我设计数据库的两个要点:
我的Java代码如下所示:
人
@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;
}
如果我需要在SQL中编写它,我就没有问题。但是使用JPA / Hibernate,一件简单的事情就变成了一场噩梦。我从一个错误反弹到另一个错误然后又回来了。
我的问题似乎来自我对IdTypeDescription的itype成员的注释。我尝试了各种方法(基于示例代码和API文档)。
这些注释组合导致我的元模型生成器不为我的静态类生成属性 IdTypeDescription _
@MapsId
@JoinColumn(name = "code")
@OneToOne(cascade = CascadeType.ALL, mappedBy="code")
public IdType itype;
这些注释组合在hibernate中导致空指针异常,因为它试图创建表:
@Id
@OneToOne(cascade = CascadeType.ALL, mappedBy="code")
public IdType itype;
或
@Id
@OneToOne(cascade = CascadeType.ALL, mappedBy="code")
@PrimaryKeyJoinColumn
public IdType itype;
错误:
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