在组合键上使用“链接”外键的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在组合键上使用“链接”外键的问题相关的知识,希望对你有一定的参考价值。
我有一些OneToOne和ManyToOne关系,我想对每个元素使用相同的主键,将键从父级“链接”到子级。
我的模型(MWE)具有三个实体:祖父母,父母和子女。祖父母与父母之间是一对一的关系,而子女与父母之间是一对多的关系,其中孩子具有由相关父母作为成员的复合键。
实现如下:
祖父母:
@Entity
@Table(name = "GRANDPARENT")
public class Grandparent implements Serializable
@Id
@Column(length = 20)
String grandparentId;
@OneToOne(mappedBy = "grandparent", cascade = CascadeType.ALL)
Parent parent;
父母:
@Entity
@Table(name = "PARENT")
public class Parent implements Serializable
@Id
@OneToOne
@JoinColumn(name = "grandparent")
Grandparent grandparent;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
List<Child> child;
儿童:
@Entity
@IdClass(ChildId.class)
@Table(name = "CHILD")
public class Child implements Serializable
@Id
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "parent", referencedColumnName = "grandparent", columnDefinition = "varchar(20)")
Parent parent;
@Id
@Column(length = 20)
String childStringId;
ChildId:
public class ChildId implements Serializable
Grandparent parent; // should have the type of the Id of "parent", according to the JPA spec
String childStringId;
// hashCode and equals methods
...
此部署失败,但有以下例外:
14:03:52,579 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 85) MSC000001: Failed to start service jboss.persistenceunit."hibernateMWE.war#pu": org.jboss.msc.service.StartException in service jboss.persistenceunit."hibernateMWE.war#pu": java.util.NoSuchElementException
at org.jboss.as.jpa@17.0.1.Final//org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:198)
at org.jboss.as.jpa@17.0.1.Final//org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:128)
at org.wildfly.security.elytron-private@1.9.1.Final//org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:649)
at org.jboss.as.jpa@17.0.1.Final//org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:212)
at org.jboss.threads@2.3.3.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
at java.base/java.lang.Thread.run(Thread.java:835)
at org.jboss.threads@2.3.3.Final//org.jboss.threads.JBossThread.run(JBossThread.java:485)
Caused by: java.util.NoSuchElementException
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:999)
at org.hibernate@5.3.10.Final//org.hibernate.internal.util.collections.JoinedIterator.next(JoinedIterator.java:47)
at org.hibernate@5.3.10.Final//org.hibernate.cfg.annotations.TableBinder.linkJoinColumnWithValueOverridingNameIfImplicit(TableBinder.java:724)
at org.hibernate@5.3.10.Final//org.hibernate.cfg.PkDrivenByDefaultMapsIdSecondPass.doSecondPass(PkDrivenByDefaultMapsIdSecondPass.java:37)
at org.hibernate@5.3.10.Final//org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1696)
at org.hibernate@5.3.10.Final//org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1653)
at org.hibernate@5.3.10.Final//org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:287)
at org.hibernate@5.3.10.Final//org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904)
at org.hibernate@5.3.10.Final//org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935)
at org.hibernate.jipijapa-hibernate5-3@17.0.1.Final//org.jboss.as.jpa.hibernate5.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44)
at org.jboss.as.jpa@17.0.1.Final//org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:170)
... 9 more
14:03:52,580 ERROR [org.jboss.as.controller.management-operation] (DeploymentScanner-threads - 2) WFLYCTL0013: Operation ("full-replace-deployment") failed - address: ([]) - failure description: "WFLYCTL0080: Failed services" => "jboss.persistenceunit.\"hibernateMWE.war#pu\"" => "java.util.NoSuchElementException
Caused by: java.util.NoSuchElementException"
如果我将ChildId中“父”字段的类型从“祖父母”更改为“父”,则部署失败,并显示MappingException: Unable to find column with logical name: grandparent in org.hibernate.mapping.Table(PARENT) and its related supertables and secondary tables
。如果我改为将其更改为String,则它将成功部署,但是持久保存实体会产生IllegalArgumentException: Can not set java.lang.String field entity.ChildId.parent to entity.Parent
。
我也试图从Child中删除JoinColumn批注,但这会导致以下异常:
Caused by: org.hibernate.MappingException: Foreign key (FKdjmtwrjnm98ag78day8q0okub:CHILD [])) must have same number of columns as the referenced primary key (PARENT [grandparent])"
我在Wildfly 17.0.1.Final上使用Hibernate 5.3.10.Final,我的数据库是MariaDB 10.0.38。我已经使用@MapsId进行了此映射,但是为了简单起见,我宁愿只使用@Ids。
您可以尝试像这样映射Parent
和Child
,使Grandparent
保持原样:
@Entity
@Table(name = "PARENT")
public class Parent implements Serializable
@Id
String id;
@OneToOne
@JoinColumn(name = "grandparent")
@MapsId
Grandparent grandparent;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
List<Child> child;
@Entity
@IdClass(ChildId.class)
@Table(name = "CHILD")
public class Child implements Serializable
@Id
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "parent", referencedColumnName = "grandparent", columnDefinition = "varchar(20)")
Parent parent;
@Id
@Column(length = 20)
String childStringId;
public class ChildId implements Serializable
String parent; // should have the type of the Id of "parent", according to the JPA spec
String childStringId;
// hashCode and equals methods
...
以上是关于在组合键上使用“链接”外键的问题的主要内容,如果未能解决你的问题,请参考以下文章