wake-up-neo.com

Wie kann ich "insert = 'false" update =' false '"auf eine composite-id-Schlüsseleigenschaft abbilden, die auch in einer Eins-zu-Viele-FK verwendet wird?

Ich arbeite an einer alten Codebasis mit einem vorhandenen DB-Schema. Der vorhandene Code verwendet SQL und PL/SQL, um Abfragen in der DB auszuführen. Wir wurden beauftragt, einen kleinen Teil der Projektdatenbank-Engine agnostisch zu machen (zuerst alles zu ändern). Wir haben uns für die Verwendung von Hibernate 3.3.2.GA und "* .hbm.xml" (im Gegensatz zu Annotationen) entschieden. Leider ist es nicht möglich, das vorhandene Schema zu ändern, da wir keine älteren Funktionen zurückgreifen können.

Das Problem, dem ich begegne, ist, wenn ich versuche, eine unidirektionale Eins-zu-Viele-Beziehung abzubilden, bei der der FK auch - Teil einer zusammengesetzten PK ist. Hier sind die Klassen und Mapping-Dateien ...

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>

Dieser Code funktioniert gut für SELECT und INSERT einer Firma mit Namen. Beim Aktualisieren eines vorhandenen Datensatzes ist ein Problem aufgetreten. Ich erhielt eine BatchUpdateException und nachdem ich die SQL-Protokolle durchgesehen hatte, sah ich, dass Hibernate versuchte, etwas zu tun, dumm ...

update COMPANY_NAME set COMPANY_ID=null where COMPANY_ID=?

Hibernate hat versucht, untergeordnete Datensätze zu trennen, bevor sie aktualisiert werden. Das Problem ist, dass dieses Feld Teil der PK ist und nicht nullfähig ist. Ich habe die schnelle Lösung gefunden, um Hibernate dazu zu bringen, dies nicht zu tun, ist das Hinzufügen von "not-null = 'true'" zum "key" -Element in der übergeordneten Zuordnung. SO jetzt sieht das Mapping so aus ...

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>

Dieses Mapping gibt die Ausnahme ...

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

Mein Problem ist jetzt, dass ich versucht habe, diese Attribute zum Schlüsseleigenschaftselement hinzuzufügen, das aber von der DTD nicht unterstützt wird. Ich habe auch versucht, es in ein Key-Many-to-One-Element zu ändern, aber das hat auch nicht funktioniert. So...

Wie kann ich "insert = 'false" update =' false '"auf eine composite-id-Schlüsseleigenschaft abbilden, die auch in einer Eins-zu-Viele-FK verwendet wird?

39
Jesse Webb

Ich denke, die gesuchte Anmerkung ist:

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

Und Sie sollten ähnliche Zuordnungen in einer hbm.xml verwenden können, wie hier (in 23.4.2):

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

81
mcyalcin

"Dino TW" hat den Link zum Kommentar Hibernate Mapping-Ausnahme: Wiederholte Spalte im Mapping für Entität bereitgestellt, die die wesentlichen Informationen enthält.

Der Link weist auf "inverse = true" im Set-Mapping hin. Ich habe es versucht und es funktioniert tatsächlich. Es ist eine solche seltene Situation, in der ein Set- und ein Composite-Schlüssel zusammenkommen. Make inverse = true, das Einfügen und Aktualisieren der Tabelle mit dem Composite-Schlüssel muss von alleine erledigt werden.

Unten kann die erforderliche Zuordnung sein, 

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