简体   繁体   English

保存具有复杂关系的实体时发生StaleStateException

[英]StaleStateException when saving entity with complex relations

The hibernate entity I am saving in the database (Oracle) has very complex relations, in the sense that it has many related entities. 从某种意义上说,我要保存在数据库(Oracle)中的休眠实体具有非常复杂的关系。 It looks something like this... 看起来像这样...

@Table(name = "t_HOP_CommonContract")
public class Contract {
    @Id
    private ContractPK id;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    private ContractGroupMember contractGroupMember;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumns({
        @JoinColumn(name = "TransactionId", referencedColumnName = "TransactionId"),
        @JoinColumn(name = "PrimaryContractId", referencedColumnName = "PrimaryContractId")
    })
    @Fetch(FetchMode.SUBSELECT)
    private List<ContractLink> contractLinks;

    // . . . . . . . 

    // A couple of more one to many relationships

    // Entity getters etc.

}

I also have a couple of more entities such as... 我还有另外两个实体,例如...

@Table(name = "t_HOP_TRS")
public class TotalReturnSwap {
    @Id
    private ContractPK id;
    // Entity Getters etc.
}

The trick is that I have to do persistence of Contract and TotalReturnSwap entities in the same transaction. 诀窍是我必须在同一事务中对ContractTotalReturnSwap实体进行持久化。

Sometimes it could be a bunch of entities that have to be persisted in the same transaction. 有时可能是一堆必须在同一事务中保留的实体。

I have noticed the following exception when I save the TotalReturnSwap entity (which is always done after I have saved the Contract entity). 保存TotalReturnSwap实体时,我已经注意到以下异常(在保存Contract实体后总是会发生此情况)。

org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is
    org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:675) \
    at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793) 
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723) 
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:147) 
    at com.rbs.fcg.publishing.DownstreamContractBusinessEventPostingService.performTDWPersistenceForContracts(DownstreamContractBusinessEventPostingService.java:102) 
    at com.rbs.fcg.publishing.DownstreamContractBusinessEventPostingService.persistContractBusinessEvent(DownstreamContractBusinessEventPostingService.java:87)
    at com.rbs.fcg.publishing.DownstreamContractBusinessEventPostingService.publish(DownstreamContractBusinessEventPostingService.java:67)
    at com.rbs.fcg.publishing.PublishingProcessor.publish(PublishingProcessor.java:76)
    at com.rbs.fcg.publishing.PublishingProcessor.process(PublishingProcessor.java:52)
    at com.rbs.are.MultiThreadedQueueItemProcessor$2.run(MultiThreadedQueueItemProcessor.java:106)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85)
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70)

Now a few points that may help while answering questions: 现在,在回答问题时可能会有所帮助的几点:

  • I am only saving (inserting) entities in database - never updating/ deleting/ reading 我只在数据库中保存(插入)实体-从未更新/删除/读取
  • I have been able to isolate this exception even in single threaded environments, so it does not look like a multi-threading, issue even though our application is multi-threaded 即使在单线程环境中,我也能够隔离此异常,因此即使我们的应用程序是多线程的,它也不像多线程问题

The error can be caused by several things: 该错误可能是由以下几种原因引起的:

  1. Flushing the data before committing the object may lead to clear all object pending for persist. 在提交对象之前刷新数据可能会导致清除所有等待持久化的对象。
  2. If object has primary key which is auto generated and you are forcing an assigned key 如果对象具有自动生成的主键,并且您正在强制分配键
  3. if you are cleaning the object before committing the object to database. 如果在将对象提交到数据库之前正在清理对象。
  4. Zero or Incorrect ID: If you set the ID to zero or something else, Hibernate will try to update instead of insert. 零或不正确的ID:如果将ID设置为零或其他值,Hibernate将尝试更新而不是插入。
  5. Object is Stale: Hibernate caches objects from the session. 对象是陈旧的:Hibernate从会话中缓存对象。 If the object was modified, and Hibernate doesn't know about it, it will throw this exception — note the StaleStateException 如果对象被修改,而Hibernate不知道,它将抛出此异常—请注意StaleStateException

I'm not taking the credit for it, found it here . 我不为此而功劳,在这里找到了它。

This happened to me under the following circumstances: 在以下情况下,这发生在我身上:

  • I created objectA in java code. 我用Java代码创建了objectA。
  • I added extant objectB to objectA as a field. 我将现存的objectB添加到objectA作为字段。 objectB has a one to one relation with objectA. objectB与objectA具有一对一关系。
  • I saved(created) objectA in the database. 我将objectA保存(创建)在数据库中。
  • When objectA was saved, objectB was updated in the database to add the id of objectA. 保存objectA后,将在数据库中更新objectB以添加objectA的ID。

  • Then I added an objectC to objectA (one objectA for many objectCs). 然后,我向objectA添加了一个objectC(对于许多objectC,一个objectA)。 I tried to update objectA and got the stalestateexception....even when using merge. 我试图更新objectA并得到stalestateexception...。即使使用合并也是如此。

The answer is that I needed to either update objectB or retrieve a fresh istance of objectA from the database 答案是我需要更新objectB或从数据库中检索objectA的新距离

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM