2012-07-31 16 views
5

Jednostka hibernacji, którą zapisuję w bazie danych (Oracle), ma bardzo złożone relacje, w tym sensie, że ma wiele powiązanych ze sobą obiektów. Wygląda to mniej więcej tak ...StaleStateException podczas zapisywania encji o złożonych relacjach

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

} 

Mam też kilka więcej podmiotów, takich jak ...

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

Sztuką jest to, że muszę zrobić trwałość Contract i TotalReturnSwap podmiotów ta sama transakcja.

Czasami może to być kilka podmiotów, które muszą być utrzymywane w tej samej transakcji.

Zauważyłem następujący wyjątek podczas zapisywania jednostki TotalReturnSwap (co zawsze jest wykonywane po tym, jak zapisałem jednostkę 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) 

Teraz kilka punktów, które mogą pomóc podczas odpowiedzi na pytania:

  • Ja tylko oszczędność (wstawianie) podmiotów w bazie danych - nigdy aktualizacji/usuwanie/odczyt
  • I udało się wyizolować ten wyjątek nawet w środowiskach z pojedynczym gwintem, więc nie wygląda na wielowątkowość, nawet jeśli nasza aplikacja jest wielowątkowa

Odpowiedz

17

Błąd może być spowodowany przez s kilka rzeczy:

  1. Płukanie danych przed zatwierdzeniem obiektu może spowodować usunięcie wszystkich obiektów oczekujących na utratę.
  2. Jeśli obiekt ma klucz podstawowy wygenerowany automatycznie i wymuszasz przypisany klucz
  3. , jeśli czyścisz obiekt przed zatwierdzeniem obiektu do bazy danych.
  4. Zero lub nieprawidłowy identyfikator: Jeśli ustawisz identyfikator na zero lub coś innego, Hibernacja spróbuje zaktualizować zamiast wstawiania.
  5. Obiekt jest stale: Hibernuj buforuje obiekty z sesji. Jeśli obiekt został zmodyfikowany i Hibernate nie wie o tym, będzie rzucać ten wyjątek - zanotować StaleStateException

Nie biorę kredytu dla niego, znalazł go here.

+0

O # 5, w jaki sposób można go rozwiązać? – Stony

+0

@Stony Być może 'Odśwież()'? – Michael

+0

@Michael Mój problem to 2 wątki modyfikuj ten sam PO w tym samym czasie; więc kiedy zapisz PO, jako powód nr 5, wyrzuć wyjątek. więc kiedy wywołać funkcję refresh() na wszelki wypadek? Jeśli przed zapisaniem(), zmiana PO po prostu zniknie. Wreszcie, użyłem blokady LockMode.PESSIMISTIC_WRITE, aby rozwiązać mój problem. Ktoś ma lepsze rozwiązanie? – Stony

0

To zdarzyło mi się w następujących okolicznościach:

  • stworzyłem objectA w kodzie Java.
  • Dodałem zachowany obiektB do obiektuA jako pole. objectB ma jeden do jeden związek z obiektemA.
  • Zapisałem (utworzony) obiekt A w bazie danych.
  • Po zapisaniu obiektu A obiektB został zaktualizowany w bazie danych, aby dodać id obiektuA.

  • Następnie dodałem objectC do objectA (jeden objectA dla wielu obiektów obiektowych ). Próbowałem zaktualizować obiektA i uzyskałem wyjątek stalestateception ... nawet przy użyciu funkcji scalania.

Odpowiedź jest, że muszę albo aktualizacji objectB lub odzyskać świeży istance z objectA z bazy

Powiązane problemy