2009-05-26 7 views
0

quand j'essaie de mettre à jour la demande de devis d'objet, Hibernate a tendance à mettre à jour sa collection enfant BQMaster et d'essayer de définir et mettre à jour l'identifiant de BQMaster qui, normalement, il ne devrait pas être autorisé.Hibernate - collection enfant Identifiant changé dans la mise à jour

Le fichier journal de postgre:
2009-05-22 11:16:53 ERREUR: clé en double violation contrainte unique "bq_masters_pkey"
2009-05-22 11:16:53 DÉCLARATION: mise à jour bq_masters mis rfq_id = $ 1, id = $ 2id = $ 3

erreur dans la console:
Causée par: java.sql.BatchUpdateException: entrée par lot 0 mise à jour bq_masters définie rf q_id = 2, id = 0 où id = 49449 a été abandonnée. Appelez-getNextException pour voir la cause .
à org.postgresql.jdbc2.AbstractJdbc2Statement $ BatchResultHandler.handle Erreur (AbstractJdbc2Statement.java:2392)
à org.postgresql.core.v3.QueryExecutorImpl.processResults (QueryExecutor Impl.java:1257)
à org.postgresql.core.v3.QueryExecutorImpl.execute (QueryExecutorImpl.ja va: 334)
à org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch (AbstractJdbc 2Statement.java:2451)
à org.hibernate.jdbc.BatchingBatcher.doExecuteBatch (BatchingBatcher.jav a: 58)
à org.hibernate.jdbc.AbstractBatcher.executeBatch (AbstractBatcher.java: 195)
. .. 32 plus

il semble très étrange car il a essayé de mettre à jour l'ID de bq_masters. Il devrait conserver l'identifiant et mettre à jour uniquement les autres champs.

Criteria crit = session.createCriteria(BQMaster.class); 
crit.add(Restrictions.eq("project",project); 
crit.setFirstResult(5); 
crit.setMaxResult(2); 
List bqMasters = crit.list(); 

RFQ rfq = (RFQ)session.get(RFQ.class, RFQId); 
rfq.setBqMasters(bqMasters); 
session.update(rfq); 

mapping Hibernate:

<class name="RFQ" table="rfq"> 
    <id name="id" column="id"> 
    <generator class="native"> 
     <param name="sequence">rfq_id_seq</param> 
    </generator> 
    </id> 

    <property name="reference" column="reference" /> 
    <property name="status" column="status" /> 
    <property name="created" column="created" /> 
    <property name="modified" column="modified" /> 

    <many-to-one name="project" class="Project" column="project_id" cascade="save-update" /> 

    <list name="subcons" table="rfq_subcons"> 
    <key column="rfq_id" /> 
    <list-index column="id"/> 
    <many-to-many class="Subcon" column="subcon_id"/> 
    </list> 

    <list name="bqMasters"> 
    <key column="rfq_id" /> 
    <list-index column="id"/> 
    <one-to-many class="BQMaster"/> 
    </list> 
</class> 

<class name="BQMaster" table="bq_masters"> 
    <id name="id" column="id"> 
    <generator class="native"> 
     <param name="sequence">bq_masters_id_seq</param> 
    </generator> 
    </id> 

    <property name="reference" column="reference" /> 
    <property name="description" column="description" /> 
    <property name="lod" column="lod" /> 
    <property name="uom" column="uom" /> 
    <property name="quantity" column="quantity" /> 
    <property name="parentId" column="parent_id" /> 
    <property name="groupId" column="group_id" /> 
    <property name="leaf" column="leaf" /> 
    <property name="active" column="active" /> 
    <property name="subcontract" column="subcontract" /> 
    <property name="created" column="created" /> 
    <property name="modified" column="modified" /> 

    <many-to-one name="project" class="Project" column="project_id" cascade="save-update" /> 

    <many-to-one name="page" class="Page" column="page_id" cascade="save-update" /> 

    <many-to-one name="rfq" class="RFQ" column="rfq_id" cascade="save-update" /> 

</class> 
structures de base de données

pour référence:

CREATE TABLE rfq 
( 
    id bigserial NOT NULL, 
    project_id bigint, 
    reference text, 
    status text, 
    created timestamp without time zone, 
    modified timestamp without time zone, 
    CONSTRAINT rfq_pkey PRIMARY KEY (id), 
    CONSTRAINT rfq_project_id_fkey FOREIGN KEY (project_id) 
    REFERENCES projects (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE 
); 

CREATE TABLE bq_masters 
(
    id bigserial NOT NULL, 
    reference varchar(100), 
    project_id bigint, 
    page_id bigint, 
    rfq_id bigint, 
    description text, 
    lod integer, 
    uom varchar(20), 
    quantity numeric, 
    parent_id bigint, 
    group_id bigint, 
    leaf boolean, 
    active boolean, 
    subcontract boolean, 
    created timestamp without time zone, 
    modified timestamp without time zone, 
    CONSTRAINT bq_masters_pkey PRIMARY KEY (id), 
    CONSTRAINT bq_masters_project_id_fkey FOREIGN KEY (project_id) 
    REFERENCES projects (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE, 
    CONSTRAINT bq_masters_page_id_fkey FOREIGN KEY (page_id) 
    REFERENCES pages (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE, 
    CONSTRAINT bq_masters_rfq_id_fkey FOREIGN KEY (rfq_id) 
    REFERENCES rfq (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE 
); 

J'ai essayé d'ajouter inverse = "true" dans RFQ un à plusieurs cartographie mais sans résultat , car il ne met pas à jour les BQMasters de l'objet RFQ correspondant.

Est-ce que quelqu'un a la moindre idée sur la résolution de ce problème? Merci d'avance.

Répondre

0

Hibernate fait exactement ce yo font en mémoire. Vous mettez les bqmasters dans la table bqMasters, et vous cartographié cette relation à la colonne rfq_id dans bqmasters, il met à jour la clé étrangère.

Vous devez utiliser inverse pour cela. La même colonne rfq_id est utilisée pour deux propriétés, une seule peut être utilisée par Hibernate.

Vous avez réellement un problème de consistance en mémoire. Si vous ajoutez un bqmaster à la liste, vous devez également mettre à jour la propriété rfq, car il contient la même relation parent-enfant et est également mappé à la même colonne de base de données. Par ailleurs, vous n'avez pas à appeler de mise à jour sur les objets déjà présents dans la session. Hibernate notifiera que l'objet a changé et le mettra à jour.

Questions connexes