2012-07-31 37 views
5

Thực thể ngủ đông mà tôi đang lưu trong cơ sở dữ liệu (Oracle) có quan hệ rất phức tạp, theo nghĩa là nó có nhiều thực thể liên quan. Nó trông giống như thế này ...StaleStateException khi lưu thực thể với quan hệ phức tạp

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

} 

Tôi cũng có một vài đơn vị hơn như ...

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

Bí quyết là tôi phải làm kiên trì của ContractTotalReturnSwap thực thể trong cùng một giao dịch.

Đôi khi có thể là một loạt các thực thể phải được lưu giữ lâu dài trong cùng một giao dịch.

Tôi đã nhận thấy ngoại lệ sau khi tôi lưu thực thể TotalReturnSwap (thường được thực hiện sau khi tôi đã lưu thực thể 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) 

Bây giờ một vài điểm có thể giúp trong khi câu hỏi trả lời:

  • Tôi chỉ tiết kiệm (chèn) các thực thể trong cơ sở dữ liệu - không bao giờ cập nhật/xóa/đọc
  • tôi đã có thể để cô lập ngoại lệ này ngay cả trong môi trường luồng đơn, do đó, nó không giống như một vấn đề đa luồng, mặc dù ứng dụng của chúng tôi là đa luồng

Trả lời

17

Lỗi có thể do mọi thứ:

  1. Làm sạch dữ liệu trước khi cam kết đối tượng có thể dẫn đến xóa tất cả đối tượng đang chờ xử lý.
  2. Nếu đối tượng có khóa chính được tạo tự động và bạn đang buộc khóa được gán
  3. nếu bạn đang làm sạch đối tượng trước khi chuyển đối tượng vào cơ sở dữ liệu.
  4. Số không hoặc ID không chính xác: Nếu bạn đặt ID thành 0 hoặc cái gì khác, Hibernate sẽ cố cập nhật thay vì chèn.
  5. Đối tượng là cũ: Hibernate lưu trữ các đối tượng từ phiên. Nếu đối tượng đã được sửa đổi và Hibernate không biết về nó, nó sẽ ném ngoại lệ này - hãy lưu ý rằng StaleStateException

Tôi không lấy tín dụng cho nó, tìm thấy nó here.

+0

Về # 5, làm thế nào chúng ta có thể giải quyết nó? – Stony

+0

@Stony Có lẽ một 'Làm mới()'? – Michael

+0

@Michael Vấn đề của tôi là 2 chủ đề sửa đổi cùng một PO cùng một lúc; vì vậy khi lưu PO, làm lý do số 5, hãy ném một ngoại lệ. vì vậy khi gọi refresh() trong trường hợp? Nếu trước khi lưu(), thay đổi cho PO sẽ biến mất. Cuối cùng, tôi đã sử dụng khóa LockMode.PESSIMISTIC_WRITE để giải quyết vấn đề của mình. Bất kỳ ai có một giải pháp tốt hơn? – Stony

0

này xảy ra với tôi trong các trường hợp sau đây:

  • Tôi tạo ra objectA trong mã java.
  • Tôi đã thêm đối tượng mở rộngB vào đối tượngA làm trường. objectB có một đến một mối quan hệ với đối tượngA.
  • Tôi đã lưu (đã tạo) đối tượngA trong cơ sở dữ liệu.
  • Khi đối tượng được lưu, đối tượngB được cập nhật trong cơ sở dữ liệu để thêm id của đối tượngA.

  • Sau đó, tôi đã thêm đối tượngC vào đối tượngA (một đối tượngA cho nhiều đối tượng ). Tôi đã cố gắng cập nhật objectA và nhận được sự nhận biết tạm thời là .... ngay cả khi sử dụng hợp nhất.

Câu trả lời là tôi cần một trong hai bản cập nhật objectB hoặc lấy một istance tươi của objectA từ cơ sở dữ liệu

Các vấn đề liên quan