Come posso mappare "insert= 'false' update= 'false'" su una proprietà chiave con id composito che viene utilizzata anche in un FK uno-a-molti?

StackOverflow https://stackoverflow.com/questions/4892925

Domanda

Sto lavorando su una base di codice legacy con uno schema DB esistente. Il codice esistente utilizza SQL e PL / SQL per eseguire query sul DB. Ci è stato assegnato il compito di rendere una piccola parte del motore di database del progetto agnostico (all'inizio, cambiare tutto alla fine). Abbiamo scelto di utilizzare i file di mappatura Hibernate 3.3.2.GA e "* .hbm.xml" (al contrario delle annotazioni). Sfortunatamente, non è possibile modificare lo schema esistente perché non siamo in grado di regredire alle funzionalità precedenti.

Il problema che riscontro è quando cerco di mappare una relazione unidirezionale uno-a-molti in cui l'FK è anche parte di una PK composita. Ecco le classi e il file di mappatura ...

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 perfettamente per SELECT e INSERT di una società con nomi. Ho riscontrato un problema quando ho provato ad aggiornare un record esistente. Ho ricevuto una BatchUpdateException e dopo aver esaminato i log SQL ho visto che Hibernate stava cercando di fare qualcosa di stupido ...

update COMPANY_NAME set COMPANY_ID=null where COMPANY_ID=?

Hibernate stava tentando di disassociare i record figlio prima di aggiornarli. Il problema è che questo campo fa parte della PK e non annulla i valori. Ho trovato che la soluzione rapida per impedire a Hibernate di farlo è aggiungere "not-null= 'true'" all'elemento "key" nella mappatura genitore. Quindi ora la mappatura potrebbe assomigliare a questa ...

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 fa l'eccezione ...

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

Il mio problema ora è che ho provato ad aggiungere questi attributi all'elemento chiave-proprietà, ma non è supportato dal DTD. Ho anche provato a cambiarlo in un elemento chiave molti a uno, ma neanche quello ha funzionato. Quindi ...

Come posso mappare "insert= 'false' update= 'false'" su una proprietà chiave con id composto che viene utilizzata anche in un FK uno-a-molti?

È stato utile?

Soluzione

Penso che l'annotazione che stai cercando sia:

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

E dovresti essere in grado di usare 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

Altri suggerimenti

"Dino TW" ha fornito il collegamento al commento Eccezione mappatura ibernazione: colonna ripetuta nella mappatura dell'entità che contiene le informazioni vitali.

Il collegamento suggerisce di fornire "inverse= true" nella mappatura del set, l'ho provato e funziona davvero.È una situazione così rara in cui una chiave Set e Composite si uniscono.Rendi inverse= true, lasciamo che l'inserimento e l'aggiornamento della tabella con la chiave Composite si occupi da solo.

Di seguito può essere la mappatura richiesta,

<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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top