Hibernate - 子集合标识符在更新中更改

发布于 2024-07-21 06:46:07 字数 5095 浏览 5 评论 0原文

当我尝试更新对象 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查看原因 .
在 org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handle 错误(AbstractJdbc2Statement.java:2392)
在 org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutor Impl.java:1257)
在 org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.ja 弗吉尼亚州:334)
在 org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc 2Statement.java:2451)
在 org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.jav 答:58)
在 org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java: 195)
... 32 more

看起来很奇怪,因为它试图更新 bq_masters 的 id。 它应该保留 id 并仅更新其他字段。

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

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>

可供参考的数据库结构:

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

我尝试在 RFQ 一对多映射中添加 inverse="true" 但无济于事,因为它不会更新相应 RFQ 对象的 BQMasters。

有人对解决这个问题有任何线索吗? 提前致谢。

when I trying to update the object RFQ , Hibernate tends to update its child collection BQMaster and trying to set and update the identifier of BQMaster which normally it should not be allowed.

The postgre log file:
2009-05-22 11:16:53 ERROR: duplicate key violates unique constraint "bq_masters_pkey"
2009-05-22 11:16:53 STATEMENT: update bq_masters set rfq_id=$1, id=$2 where id=$3

error in console:
Caused by: java.sql.BatchUpdateException: Batch entry 0 update bq_masters set rf
q_id=2, id=0 where id=49449
was aborted. Call getNextException to see the cause
.

at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handle
Error(AbstractJdbc2Statement.java:2392)

at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutor
Impl.java:1257)

at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.ja
va:334)

at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc
2Statement.java:2451)

at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.jav
a:58)

at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:
195)

... 32 more

It seems very weird as it tried to update the id of bq_masters. It should keep the id and update only the other fields.

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

Hibernate mapping:

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

database structures for reference :

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

I have tried adding inverse="true" in RFQ one-to-many mapping but to no avail, as it doesn't update the BQMasters of corresponding RFQ object.

Does anybody has any clue on solving this problem? Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

百善笑为先 2024-07-28 06:46:07

Hibernate 所做的正是您在内存中所做的事情。 您将 bqmasters 放入 bqMasters 表中,并将此关系映射到 bqmasters 中的 rfq_id 列,因此它会更新外键。

为此,您必须使用逆函数。 同一列 rfq_id 用于两个属性,Hibernate 只能使用一个属性。

你实际上存在记忆的一致性问题。 如果将 bqmaster 添加到列表中,还需要更新它的 rfq 属性,因为它拥有相同的父子关系,并且也映射到相同的数据库列。

顺便说一句,您不必对会话中已有的对象调用更新。 Hibernate 将通知对象已更改并更新它。

Hibernate does exactly what yo are doing in memory. You are putting the bqmasters into the bqMasters table, and you mapped this relation to the rfq_id column in bqmasters, so it updates the foreign key.

You must use inverse for this. The same column rfq_id is used for two properties, only one could be used by Hibernate.

You have actually a consistence problem in memory. If you add a bqmaster to the list, you also need to update the rfq property of it, because it is holding the same parent-child relation and also mapped to the same database column.

By the way, you don't have to call update on objects that are already in the session. Hibernate will notify that the object has changed and will update it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文