2011-02-03 16 views
37

Sto lavorando su un codice base legacy con uno schema DB esistente. Il codice esistente utilizza SQL e PL/SQL per eseguire query sul DB. Ci è stato affidato il compito di fare una piccola parte del database del progetto agnostico del motore (in un primo momento, cambiare tutto alla fine). Abbiamo scelto di utilizzare Hibernate 3.3.2.GA e file di mapping "* .hbm.xml" (a differenza delle annotazioni). Sfortunatamente, non è possibile modificare lo schema esistente perché non possiamo regredire alcuna funzionalità legacy.Come posso mappare "insert = 'false' update = 'false'" su una proprietà-chiave compos-id che viene anche usata in un FK one-to-many?

Il problema che sto incontrando è quando sto cercando di mappare un uni-direzionale, relazione uno-a-molti dove l'FK è anche parte di un PK composito. Qui ci sono le classi e file di mapping ...

CompanyEntity.java

public class CompanyEntity { 
    private Integer id; 
    private Set<CompanyNameEntity> names; 
    ... 
} 

CompanyNameEntity.java

public class CompanyNameEntity implements Serializable { 
    private Integer id; 
    private String languageId; 
    private String name; 
    ... 
} 

CompanyNameEntity.hbm.xml

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
     "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
     "http://www.jboss.org/dtd/hibernate/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping package="com.example"> 

    <class name="com.example.CompanyEntity" table="COMPANY"> 
     <id name="id" column="COMPANY_ID"/> 
     <set name="names" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false"> 
      <key column="COMPANY_ID"/> 
      <one-to-many entity-name="vendorName"/> 
     </set> 
    </class> 

    <class entity-name="companyName" name="com.example.CompanyNameEntity" table="COMPANY_NAME"> 
     <composite-id> 
      <key-property name="id" column="COMPANY_ID"/> 
      <key-property name="languageId" column="LANGUAGE_ID"/> 
     </composite-id> 
     <property name="name" column="NAME" length="255"/> 
    </class> 

</hibernate-mapping> 

Questo codice funziona solo va bene per SELECT e INSERT di un'azienda con nomi. Ho riscontrato un problema quando ho provato ad aggiornare e il record esistente. Ho ricevuto un BatchUpdateException e dopo aver guardato attraverso i registri SQL ho visto Hibernate stava cercando di fare qualcosa di stupido ...

update COMPANY_NAME set COMPANY_ID=null where COMPANY_ID=? 

Hibernate stava cercando di record figlio dis-associare prima di aggiornare loro. Il problema è che questo campo è parte del PK e non annullabile. Ho trovato la soluzione rapida per far sì che Hibernate non lo facesse aggiungendo "not-null = 'true'" all'elemento "chiave" nel mapping genitore. mappatura così ora maggio si presenta così ...

CompanyNameEntity.hbm.xml

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
     "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
     "http://www.jboss.org/dtd/hibernate/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping package="com.example"> 

    <class name="com.example.CompanyEntity" table="COMPANY"> 
     <id name="id" column="COMPANY_ID"/> 
     <set name="names" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false"> 
      <key column="COMPANY_ID" not-null="true"/> 
      <one-to-many entity-name="vendorName"/> 
     </set> 
    </class> 

    <class entity-name="companyName" name="com.example.CompanyNameEntity" table="COMPANY_NAME"> 
     <composite-id> 
      <key-property name="id" column="COMPANY_ID"/> 
      <key-property name="languageId" column="LANGUAGE_ID"/> 
     </composite-id> 
     <property name="name" column="NAME" length="255"/> 
    </class> 

</hibernate-mapping> 

Questa mappatura dà l'eccezione ...

org.hibernate.MappingException: Repeated column in mapping for entity: companyName column: COMPANY_ID (should be mapped with insert="false" update="false") 

mio problema ora è che ho provato a aggiungi questi attributi all'elemento key-property ma non è supportato dal DTD. Ho anche provato a cambiarlo in un elemento chiave-molti-a-uno, ma anche questo non ha funzionato. Quindi ...

Come si può mappare "insert = 'false' update = 'false'" su una proprietà chiave-id composito che viene utilizzata anche in un FK one-to-many?

+0

Dopo aver guardato il Hibernate annotazioni doc, sembra che potrei essere in grado di creare la mappatura desiderata con annotazioni JPA/Hibernate. Sperimenterò un po 'di più e pubblicherò i miei risultati. –

+0

La mappatura che sto tentando di specificare NON è possibile usando i file * .hbm.xml. L'unico modo per farlo è usare le annotazioni come indicato nella risposta di mcyalcin sotto. –

+1

Immagino che questo post possa risolvere il problema nella configurazione XML, http://stackoverflow.com/questions/9381029/hibernate-mapping-exception-repeated-column-in-mapping-for-entity –

risposta

77

Penso che l'annotazione che si sta cercando è:

public class CompanyName implements Serializable { 
//... 
@JoinColumn(name = "COMPANY_ID", referencedColumnName = "COMPANY_ID", insertable = false, updatable = false) 
private Company company; 

e si dovrebbe essere in grado di utilizzare mappature simili in un hbm.xml come mostrato qui (in 23.4.2):

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-mappings.html

+0

Grazie per la risposta. All'interno del collegamento alla documentazione di JBoss che hai fornito, non contiene alcun esempio del caso in cui sto riscontrando problemi. Ho provato ad usare le mappature esattamente come hanno mostrato e ancora non ha funzionato per me. Sembra che la particolare mappatura che sto cercando di realizzare non sia possibile con l'attuale specifica DTM HBM. Detto questo, la soluzione con annotazioni non affronta lo stesso problema che sto vivendo quindi è una buona soluzione per chiunque abbia la possibilità di utilizzare le annotazioni. Normalmente raccomando le annotazioni a tutti coloro che hanno la scelta. –

+0

Interessante. Ho utilizzato solo annotazioni con Hibernate fino ad ora, trovando ciò più conveniente, ma ho pensato che la funzionalità di annotazione fosse un sottoinsieme delle definizioni di mapping xml, non il contrario. Mi occuperò degli xmls, perché se c'è davvero una funzionalità mancante, dovrebbe essere segnalato un bug. Sono felice che la risposta sia stata d'aiuto! – mcyalcin

+1

Ma se voglio inserire e aggiornare, c'è qualche altro lavoro da fare per uscire da questo? Perché suppongo, insertable = false e updatable = false non mi permetteranno di cambiare la "compagnia". – kinshuk4

0

"Dino TW" ha fornito il collegamento al commento Hibernate Mapping Exception : Repeated column in mapping for entity che ha le informazioni vitali.

Il collegamento suggerisce di fornire "inverse = true" nella mappatura dell'insieme, l'ho provato e funziona effettivamente.È una situazione talmente rara in cui un tasto Set e Composite si uniscono. Make inverse = true, lasciamo l'aggiornamento & dell'inserto della tabella con il tasto Composite per essere curato da solo.

seguito può essere la mappatura necessaria,

<class name="com.example.CompanyEntity" table="COMPANY"> 
    <id name="id" column="COMPANY_ID"/> 
    <set name="names" inverse="true" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false"> 
     <key column="COMPANY_ID" not-null="true"/> 
     <one-to-many entity-name="vendorName"/> 
    </set> 
</class>