2010-11-26 12 views
5

Tengo tres tablas:Mapeo JPA (Hibernate, EclipseLink): ¿por qué este código no funciona (cadena de 2 relaciones usando JPA 2.0, @EmbeddedId compuesto 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) 
); 

lógica simple: bares -> Foos -> PostAddresses todo por (contact_id, ordinal_nbr), lo que significa.

Aquí las seis entidades y las clases de teclas compuestas respectivas.

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

    ... 
} 

Es realmente nada especial, Bar referencia Foo, Foo referencia PostAddress, todo ello a través de clases clave compuesta. Como las claves externas son compuestas y forman parte de PK, debo anidar las clases de ID en las clases de ID. Pensé que esto es correcto. Sin embargo, consigo los siguientes seguimientos de pila con Hibernate 3.6 y 2.2.0 EclipseLink

Hibernate:

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]2c1 
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 da absolutamente ninguna pista sobre qué clase es la ofender a uno. Al menos Hibernate me dice acerca de un problema con la anotación @MapsId y la clase Foo:

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

¿Qué pasa aquí?

PD: Puedo armar un SSCCE, solo pregunte si necesita uno (JavaSE, HSQLDB, Ant, Hibernate 3.6).

Respuesta

2

la simple eliminación de la anotación @Embedded desde el interior de los tipos EmbeddedId que hacen referencia a los EmbeddedIds dependientes pueden resolver su problema .:

 
    @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): Otro tema es el uso de la FooId. Esta clase no debe ser utilizada. La clase de ID para Foo Enitity es PostAddressId y OneToOne "postAddress" simplemente debe marcar @Id y no @MapsId. Del mismo modo, BarId no debe tener un Embedded definido, sino que debe hacer referencia directamente a PostAddressId. La asignación de barras que hace referencia a PostAddress debe usar MapsId.

Por favor, presente un error en contra de EclipseLink para la terrible excepción y si eliminar el @Embedded y las otras actualizaciones en la edición no resuelve su problema, también presente un error de EclipseLink.

+0

Intenté esto antes de publicarlo y lo intenté de nuevo, pero tanto con y sin @Embedded no funciona. Voy a presentar un error ahora. – Kawu

+2

Error de EclipseLink archivado aquí: https://bugs.eclipse.org/bugs/show_bug.cgi?id=331386 – Kawu

+0

Gracias por agregar el informe de errores. Me salvó el día. Resulta que todavía estoy usando EclipseLink 2.2.x, y simplemente cambiando mi pom para usar Eclipse 2.3.x solucioné este problema de NPE. – lsiu

Cuestiones relacionadas