2010-11-26 6 views
5

J'ai trois tables:Mappage JPA (Hibernate, EclipseLink): pourquoi ce code ne fonctionne-t-il pas (chaîne de 2 relations utilisant JPA 2.0, @EmbeddedId composite 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) 
); 

logiques simples: Bars -> Foos -> PostAddresses tous par (contact_id, ordinal_nbr), tout cela signifie.

Voici les six classes d'entité et de clé composite respectives.

@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; 

    ... 
} 

Il est vraiment rien de spécial, références Bar Foo, Foo référence PostAddress, le tout via composite classe clé. Puisque les clés étrangères sont composites et font partie du PK, je dois imbriquer les classes ID dans les classes ID. Je pensais que c'est correct. Cependant, je reçois les traces de pile suivantes avec Hibernate 3.6 et 2.2.0 EclipseLink

Mise en veille prolongée:

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 

EclipseLink:

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 

EclipseLink me donne absolument aucune indication quant à quelle classe est la offenser un. Au moins Hibernate me parle d'un problème avec l'annotation @MapsId et la classe Foo:

org.hibernate.AssertionFailure: Unexpected nested component on the referenced entity when mapping a @MapsId: tld.transmuc.model.Foo 

Quel est le problème ici? PS: Je peux créer un SSCCE, il suffit de demander si vous en avez besoin (JavaSE, HSQLDB, Ant, Hibernate 3.6).

Répondre

2

l'annotation enlevant simplement @Embedded à l'intérieur des types EmbeddedId qui font référence à la EmbeddedIds charge peut résoudre votre problème .:

 
    @Embeddable 
    public class FooId implements Serializable 
    { 
     // no annotation. 
     private PostAddressId postAddressId; //just one field! 

     ... 
    } 

    ... 
     @MapsId(value = "postAddressId") 
     @OneToOne 
     @JoinColumns(value = {@JoinColumn(name = "contact_id", referencedColumnName = "contact_id"), @JoinColumn(name = "ordinal_nbr", referencedColumnName = "ordinal_nbr")}) 
     private PostAddress postAddress = null; 

(EDIT): Une autre question est l'utilisation du fooid. Cette classe ne devrait pas être utilisée. La classe d'ID pour Foo Enitity est PostAddressId et OneToOne "postAddress" doit simplement être marqué @Id et non @MapsId. De même BarId ne doit pas avoir de Embedded défini mais doit directement référencer PostAddressId. Le mappage de barre qui référence PostAddress doit utiliser MapsId.

Veuillez déposer un bogue sur EclipseLink pour la terrible exception et si la suppression de @Embedded et des autres mises à jour de l'édition ne résout pas votre problème, veuillez également créer un bogue EclipseLink.

+0

J'ai essayé ceci avant de poster et j'ai juste essayé encore, mais les deux avec et sans @Embedded ne fonctionnent pas. Je vais déposer un bug maintenant. – Kawu

+2

EclipseLink bug déposé ici: https://bugs.eclipse.org/bugs/show_bug.cgi?id=331386 – Kawu

+0

Merci d'avoir ajouté le rapport de bogue. Cela a sauvé ma journée. Il s'avère que j'utilise toujours EclipseLink 2.2.x, et le fait de changer mon pom pour utiliser Eclipse 2.3.x a résolu ce problème NPE. – lsiu

Questions connexes