3 테이블 :JPA (Hibernate, EclipseLink) 매핑 : JPA 2.0, @EmbeddedId 복합 PK-FK를 사용하는이 코드가 왜 작동하지 않습니까?
CREATE TABLE PostAddresses
(
contact_id INTEGER NOT NULL,
ordinal_nbr SMALLINT NOT NULL,
PRIMARY KEY (contact_id, ordinal_nbr)
);
CREATE TABLE Foos
(
contact_id INTEGER NOT NULL,
ordinal_nbr SMALLINT NOT NULL,
PRIMARY KEY (contact_id, ordinal_nbr),
FOREIGN KEY (contact_id, ordinal_nbr) REFERENCES PostAddresses (contact_id, ordinal_nbr)
);
CREATE TABLE Bars
(
contact_id INTEGER NOT NULL,
ordinal_nbr SMALLINT NOT NULL,
numba INTEGER NOT NULL,
PRIMARY KEY (contact_id, ordinal_nbr, numba),
FOREIGN KEY (contact_id, ordinal_nbr) REFERENCES Foos (contact_id, ordinal_nbr)
);
간단한 로직 : 바 -> Foos -> PostAddresses 모두 (contact_id, ordinal_nbr), 그것이 무엇이든간에.
6 개의 엔티티와 각각의 복합 키 클래스.
@Entity
@Table(name = "PostAddresses")
public class PostAddress implements Serializable
{
@EmbeddedId
private PostAddressId embeddedId;
...
}
@Embeddable
public class PostAddressId implements Serializable
{
@Column(name = "contact_id")
private Integer contactId;
@Column(name = "ordinal_nbr")
private Integer ordinalNbr = 1;
...
}
@Entity
@Table(name = "Foos")
public class Foo implements Serializable
{
@EmbeddedId
private FooId embeddedId;
@MapsId(value = "postAddressId")
@OneToOne
@JoinColumns(value = {@JoinColumn(name = "contact_id", referencedColumnName = "contact_id"), @JoinColumn(name = "ordinal_nbr", referencedColumnName = "ordinal_nbr")})
private PostAddress postAddress = null;
...
}
@Embeddable
public class FooId implements Serializable
{
@Embedded
private PostAddressId postAddressId; //just one field!
...
}
@Entity
@Table(name = "Bars")
public class Bar implements Serializable
{
@EmbeddedId
private BarId embeddedId;
...
}
@Embeddable
public class BarId implements Serializable
{
@Embedded
private FooId fooId;
@Column(name = "numba")
private Integer numba;
...
}
Bar는 Foo를 참조하고, Foo는 PostAddress를 참조하며, 모두 복합 키 클래스를 통해 특별합니다. 외래 키는 복합 키이고 PK의 일부이기 때문에 ID 클래스를 ID 클래스에 중첩시켜야합니다. 나는 이것이 정확하다고 생각했다. 그러나 하이버 네이트 3.6과 이클립스 링크 2.2.0
하이버 네이트
org.hibernate.AssertionFailure: Unexpected nested component on the referenced entity when mapping a @MapsId: tld.transmuc.model.Foo
at org.hibernate.cfg.CopyIdentifierComponentSecondPass.doSecondPass(CopyIdentifierComponentSecondPass.java:101)
at org.hibernate.cfg.Configuration.processSecondPassesOfType(Configuration.java:1424)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1388)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1345)
at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1477)
at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:193)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1096)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:278)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:362)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:56)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
at tld.transmuc.Main.main(Main.java:27)
Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: transmuc] Unable to configure EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:374)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:56)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
at tld.transmuc.Main.main(Main.java:27)
Caused by: org.hibernate.AssertionFailure: Unexpected nested component on the referenced entity when mapping a @MapsId: tld.transmuc.model.Foo
at org.hibernate.cfg.CopyIdentifierComponentSecondPass.doSecondPass(CopyIdentifierComponentSecondPass.java:101)
at org.hibernate.cfg.Configuration.processSecondPassesOfType(Configuration.java:1424)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1388)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1345)
at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1477)
at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:193)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1096)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:278)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:362)
... 4 more
이클립스 링크 :
Exception in thread "main" Local Exception Stack:
Exception [EclipseLink-30005] (Eclipse Persistence Services - 2.2.0.v20101118-r8514): org.eclipse.persistence.exceptions.PersistenceUnitLoadingException
Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: [email protected]
Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.2.0.v20101118-r8514): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [transmuc] failed.
Internal Exception: java.lang.NullPointerException
at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:126)
at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:136)
at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:65)
at javax.persistence.Persistence.createEntityManagerFactory(Unknown Source)
at javax.persistence.Persistence.createEntityManagerFactory(Unknown Source)
at tld.transmuc.Main.main(Main.java:27)
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.2.0.v20101118-r8514): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [transmuc] failed.
Internal Exception: java.lang.NullPointerException
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:1021)
at org.eclipse.persistence.internal.jpa.deployment.JPAInitializer.callPredeploy(JPAInitializer.java:95)
at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:127)
... 4 more
Caused by: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.2.0.v20101118-r8514): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [transmuc] failed.
Internal Exception: java.lang.NullPointerException
at org.eclipse.persistence.exceptions.EntityManagerSetupException.predeployFailed(EntityManagerSetupException.java:210)
... 7 more
Caused by: java.lang.NullPointerException
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.EmbeddedIdAccessor.process(EmbeddedIdAccessor.java:189)
at org.eclipse.persistence.internal.jpa.metadata.MetadataDescriptor.processMappingAccessors(MetadataDescriptor.java:1417)
at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.ClassAccessor.processMappingAccessors(ClassAccessor.java:1405)
at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.processMappingAccessors(EntityAccessor.java:1061)
at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.process(EntityAccessor.java:601)
at org.eclipse.persistence.internal.jpa.metadata.MetadataProject.processStage2(MetadataProject.java:1464)
at org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor.processORMMetadata(MetadataProcessor.java:483)
at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processORMetadata(PersistenceUnitProcessor.java:453)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:975)
... 6 more
이클립스 링크는 절대로 어떤 클래스에 대한 힌트를주지 않는다. 죄송합니다. 최소한 Hibernate는 @MapsId annotation과 Foo 클래스에 대한 문제를 알려줍니다.
org.hibernate.AssertionFailure: Unexpected nested component on the referenced entity when mapping a @MapsId: tld.transmuc.model.Foo
무엇이 잘못 되었나요?
추신 : SSCCE를 만들 수 있습니다. JavaSE, HSQLDB, Ant, Hibernate 3.6이 필요한지 물어보십시오.
나는 게시하기 전에 이것을 시도했지만 방금 다시 시도했지만, @Embedded이 있거나없는 경우 모두 작동하지 않습니다. 나는 지금 버그를 제기 할 것이다. – Kawu
EclipseLink 버그가 여기에 접수되었습니다. https://bugs.eclipse.org/bugs/show_bug.cgi?id=331386 – Kawu
버그 보고서를 추가해 주셔서 감사합니다. 그것은 내 하루를 구했다. 필자는 여전히 EclipseLink 2.2.x를 사용하고 있으며 Eclipse 2.3.x를 사용하기 위해 내 POM을 변경하면이 NPE 문제가 해결되었습니다. – lsiu