Comment puis-je cartographier «insert = 'false' update = 'false'» sur une property clé composite-id qui est également utilisée dans un FK un-à-plusieurs?

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

Question

Je travaille sur une base de code héritée avec un schéma de base de données existant. Le code existant utilise SQL et PL / SQL pour exécuter des requêtes sur la base de données. Nous avons été chargés de faire une petite partie de l'agnostique de moteur de base de données de projet (au début, de tout changer éventuellement). Nous avons choisi d'utiliser Hibernate 3.3.2.ga et des fichiers de mappage "* .hbm.xml" (par opposition aux annotations). Malheureusement, il n'est pas possible de modifier le schéma existant car nous ne pouvons pas régresser les caractéristiques héritées.

Le problème que je rencontre est lorsque j'essaie de cartographier une relation unidirectionnelle et un-à-plusieurs où le FK est aussi partie d'un PK composite. Voici les classes et le fichier de mappage ...

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>

Ce code fonctionne très bien pour sélectionner et insérer une entreprise avec des noms. J'ai rencontré un problème lorsque j'ai essayé de mettre à jour et un enregistrement existant. J'ai reçu un batchupdateException et après avoir parcouru les journaux SQL, j'ai vu Hibernate essayait de faire quelque chose stupide...

update COMPANY_NAME set COMPANY_ID=null where COMPANY_ID=?

Hibernate essayait de dissocier les enregistrements des enfants avant de les mettre à jour. Le problème est que ce champ fait partie du PK et non nulle. J'ai trouvé la solution rapide pour que Hibernate ne fasse pas cela est d'ajouter "not-null = 'true'" à l'élément "clé" dans le mappage parent. Alors maintenant, le mappage peut ressemble à ceci ...

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>

Cette cartographie donne l'exception ...

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

Mon problème est maintenant que j'ai essayé d'ajouter ces attributs à l'élément de propriété clé, mais cela n'est pas pris en charge par le DTD. J'ai également essayé de le changer en un élément clé à un, mais cela n'a pas fonctionné non plus. Alors...

Comment puis-je cartographier "insert = 'false' update = 'false'" sur une property clé composite-id qui est également utilisée dans un FK un-à-plusieurs?

Était-ce utile?

La solution

Je pense que l'annotation que vous recherchez est:

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

Et vous devriez pouvoir utiliser des mappages similaires dans un HBM.XML comme indiqué ici (en 23.4.2):

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

Autres conseils

"Dino TW" a fourni le lien vers le commentaire Exception de mappage hibernate: colonne répétée en mappage pour l'entité qui a les informations vitales.

Le lien suggère de fournir "inverse = true" dans le mappage de set, je l'ai essayé et cela fonctionne réellement. C'est une situation si rare dans laquelle un ensemble et une clé composite se réunissent. Faire inverse = true, nous laissons l'insert et la mise à jour du tableau avec une clé composite à prendre en charge par lui-même.

Ci-dessous peut être la cartographie requise,

<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>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top