Hibernate - идентификатор дочерней коллекции изменен в обновлении - PullRequest
0 голосов
/ 26 мая 2009

когда я пытаюсь обновить объект RFQ, Hibernate стремится обновить свою дочернюю коллекцию BQMaster и пытается установить и обновить идентификатор BQMaster, который обычно не должен быть разрешен.

Файл журнала postgre:
2009-05-22 11:16:53 ОШИБКА: дубликат ключа нарушает уникальное ограничение "bq_masters_pkey"
2009-05-22 11:16:53 ЗАЯВЛЕНИЕ: обновите bq_masters set rfq_id = $ 1, id = $ 2 , где id = 3

ошибка в консоли:
Причина: java.sql.BatchUpdateException: пакетная запись 0 обновление bq_masters set rf q_id = 2, id = 0, где id = 49449 был прерван. Вызовите getNextException, чтобы увидеть причину .
at org.postgresql.jdbc2.AbstractJdbc2Statement $ BatchResultHandler.handle Ошибка (AbstractJdbc2Statement.java:2392)
at org.postgresql.core.v3.QueryExecutorImpl.processResults (QueryExecutor Impl.java:1257)
at org.postgresql.core.v3.QueryExecutorImpl.execute (QueryExecutorImpl.ja ва: 334)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch (AbstractJdbc 2Statement.java:2451)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch (BatchingBatcher.jav а: 58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch (AbstractBatcher.java: 195)
... еще 32

Это кажется очень странным, поскольку он пытался обновить идентификатор bq_masters. Следует сохранить идентификатор и обновлять только остальные поля.

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

Отображение гибернации:

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

структуры базы данных для справки:

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

Я попытался добавить inverse = "true" в сопоставлении один-ко-многим в RFQ, но безрезультатно, поскольку он не обновляет BQMasters соответствующего объекта RFQ.

Кто-нибудь знает, как решить эту проблему? Заранее спасибо.

1 Ответ

0 голосов
/ 26 мая 2009

Hibernate делает именно то, что вы делаете в памяти. Вы помещаете bqmasters в таблицу bqMasters и отображаете это отношение в столбце rfq_id в bqmasters, поэтому он обновляет внешний ключ.

Вы должны использовать обратное для этого. Один и тот же столбец rfq_id используется для двух свойств, только один может использоваться Hibernate.

У вас на самом деле проблема с консистенцией в памяти. Если вы добавляете bqmaster в список, вам также необходимо обновить его свойство rfq, так как оно содержит такое же отношение родитель-потомок и также сопоставлено с тем же столбцом базы данных.

Кстати, вам не нужно вызывать update для объектов, которые уже находятся в сеансе. Hibernate уведомит об изменении объекта и обновит его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...