2015-03-26 16 views
10

Stiamo traducendo vecchia configurazione basato su XML per la configurazione base di annotazioneclasse Hibernate @Embeddable che si estende un'altra classe @Embeddable, Proprietà non trovato per la mappatura @OneToMany

Situazione

C'è una classe che viene annotata come @Embeddable(ParentPk.java), un'altra classe estende questa classe che è @Embeddable(ChildPk.java), questo ChildPk.java viene utilizzato come chiave primaria composita in SomeOwnerClass.java, che ha relazione esterna con un'altra classe SomeChildTable.java e tende a utilizzare le proprietà col1 e col2 che sono disponibili in classe genitrice di ChildPk.java ma quando query viene eseguita Hibernate non trova col1 e col2 piuttosto se copio col1 e col2 in ChildPk.java dalla classe genitore ogni cosa funziona bene.

Di seguito frammento di codice di SomeOwnerClass.java che si riferisce a col1 e col2

> @OneToMany(orphanRemoval = true, fetch=FetchType.EAGER) 
>  @Cascade(value = {CascadeType.ALL,CascadeType.SAVE_UPDATE}) 
>  @Fetch(FetchMode.JOIN) 
>  @JoinColumns({ 
>  @JoinColumn(name="COL_1",insertable=false,updatable=false,referencedColumnName="COL_1"), 
>  @JoinColumn(name="COL_2",insertable=false,updatable=false,referencedColumnName="COL_2"), 
>  @JoinColumn(name="COL_3",insertable=false,updatable=false,referencedColumnName="COL_3"), 
>  }) private Set<SomeChildTable> collection = new 
> HashSet<SomeChildTable>(); 

Qualunque soluzione per questa situazione?

ParentPk.java

@Embeddable 
    public class ParentPk implements Serializable { 

     @Column(name="COL_1") 
     private String col1; 

     @Column(ame="COL_2") 
     private String col2; 

    } 

ChildPk.java

@Embeddable 
public class ChildPk extends ParentPk implements Serializable { 

    @Column(name="COL_3") 
    private String col3; 
} 

SomeOwnerClass.java

@Entity 
@Table(name="FOO") 
public class SomeOwnerClass implements Serializable { 

    @EmbeddedId 
     @AttributeOverrides({@AttributeOverride(name="col1", [email protected](name="COL_1",length=38))}) 
     private ChildPk childPk = new ChildPk(); 

     @OneToMany(orphanRemoval = true, fetch=FetchType.EAGER) 
     @Cascade(value = {CascadeType.ALL,CascadeType.SAVE_UPDATE}) 
     @Fetch(FetchMode.JOIN) 
     @JoinColumns({ 
     @JoinColumn(name="COL_1",insertable=false,updatable=false,referencedColumnName="COL_1"), 
     @JoinColumn(name="COL_2",insertable=false,updatable=false,referencedColumnName="COL_2"), 
     @JoinColumn(name="COL_3",insertable=false,updatable=false,referencedColumnName="COL_3"), 
     }) 
    private Set<SomeChildTable> collection = new HashSet<SomeChildTable>(); 
} 

Eccezione

org.hibernate.MappingException: Unable to find column with logical name: COL_1 in SomeOwnerClass 
    at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:587) 
    at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:258) 
    at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1451) 
    at org.hibernate.cfg.annotations.CollectionBinder.bindOneToManySecondPass(CollectionBinder.java:864) 
    at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:779) 
    at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:728) 
    at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70) 
    at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1695) 
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1424) 
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844) 
    at com.foo.mypackage.ParentHibernateUtil.initiateSessionFactory(ParentHibernateUtil.java:112) 
    at com.foo.mypackage.ParentHibernateUtil.getSessionFactory(ParentHibernateUtil.java:131) 
    at com.foo.mypackage.GenericHibernateDAO.getSession(GenericHibernateDAO.java:36) 
    at com.foo.mypackage.GenericHibernateDAO.beginTransaction(GenericHibernateDAO.java:63) 
    at com.foo.mypackage.MarsTest.main(MyTest.java:22) 

ulteriori dettagli ho cercato di mappare la configurazione basato su XML per la configurazione base di annotazione di seguito è di configurazione basato su XML vecchio che funziona bene in termini di ereditarietà.

ChildPk.java convertito @Embedable estendentesi ParentPk.java

<class name="SomeOwnerClassDetail" table="FOO_DETAIL"> 

     <composite-id class="ChildPk" 
      name="childPk"> 
      <key-property name="col1" column="COL_1" type="java.lang.Long"/> 
      <key-property name="col2" column="COL_2" length="32"/> 
      <key-property name="col3" column="COL_3" length="3"/> 
     </composite-id> 
    </class> 

supra col1 col2 mappatura e sono ereditato da ParentPk.java che sono accessibili se ChildPk viene utilizzata come chiave esterna SomeOwnerClass. java in xml mapping ma non in mapping annotato.

Non riesco a modificare la struttura della mia classe in quanto è un'applicazione legacy.

SomeOwnerClass.java

<set name="someDetailKey" cascade="all,delete-orphan,save-update" lazy="false" fetch="join" > 
     <key foreign-key="FOO_Foreign_Key" > 
      <column name="COL_1"/> 
      <column name="COL_2"/> 
      <column name="COL_3"/> 
     </key> 
     <one-to-many class="ChildPk" /> 
    </set> 

+0

Mi chiedo se qualcuno ha letto questa domanda? –

risposta

12

Hibernate non supporta l'ereditarietà di @Embeddable componente:

Un oggetto incorporabile non può essere persistettero direttamente, o interrogati, può essere persisteva solo o interrogato nel contesto del suo genitore. Un oggetto incorporabile non ha un ID o una tabella. Le specifiche JPA non supportano l'ereditarietà di oggetti incorporabili, sebbene alcuni provider JPA possano consentirlo.

- Java_Persistence/Embeddables.

Le specifiche JPA non supporta gli oggetti incorporabili dover eredità
Così non si può fare uso di eredità in @Embeddable.

Si può provare a farlo completando l'id genitore come proprietà dell'ID figlio.

+0

Grazie per la tua risposta, ma la stessa relazione di classe funziona bene con la configurazione basata su XML, ho bisogno dell'alternativa in annotazione. Ho aggiunto ulteriori dettagli "Dettagli aggiuntivi" –

+0

+1 perché è una risposta valida se significa che non dovrebbe (generalmente) essere un'annotazione per questo disponibile –

8

È possibile implementare l'ereditarietà tra le classi @Embeddable. Devi solo annotare la classe genitore con @MappedSuperclass.

Così, ad es .:

@Embeddable 
@MappedSuperclass 
public class Parent { 
    @Basic 
    private String parentProperty; 

    // ... getters/setters 
} 

@Embeddable 
public class Child extends Parent { 
    @Basic 
    private String childProperty; 

    // ... getters/setters 
} 

In questo modo Hibernate (testato con 5.x) mapperà sia parentProperty e childProperty correttamente nella classe Child.

+1

Funziona anche su Hibernate 4.2. –