2011-07-14 16 views
5

Trong ứng dụng web của tôi, tôi có một số chủ đề có khả năng truy cập cùng một dữ liệu đồng thời tại sao tôi quyết định thực hiện lạc quan (phiên bản) và khóa bi quan với Hibernate.Làm thế nào để khóa và tải lại một thực thể đúng

Hiện nay tôi sử dụng mẫu sau để khóa một thực thể và thực hiện các hoạt động ghi trên đó (sử dụng quản lý Springs giao dịch và ranh giới giao dịch với @Transactional):

@Transactional 
public void doSomething(entity) { 
    session.lock(entity, LockMode.UPGRADE); 
    session.refresh(entity); 

    // I change the entity itself as well as entites in a relationship. 
    entity.setBar(...); 
    for(Child childEntity : entity.getChildren()) { 
     childEntity.setFoo(...); 
    } 
} 

Tuy nhiên, đôi khi tôi nhận được StaleObjectException khi @ Giao dịch là đỏ bừng mà nói với tôi rằng một ChildEntity đã được sửa đổi đồng thời và bây giờ có một phiên bản sai.

Tôi đoán tôi là không làm mới chính xác entity và con của nó vì vậy tôi đang làm việc với dữ liệu cũ. Ai đó có thể chỉ ra cách để đạt được điều này? Một số suy nghĩ của tôi bao gồm xóa bối cảnh kiên trì (phiên) hoặc gọi lại số session.lock(entity, LockMode.READ), nhưng tôi không chắc điều gì đúng ở đây.

Cảm ơn sự giúp đỡ của bạn!

Trả lời

0

Tại sao bạn tạo "LockMode.UPGRADE" và khóa lạc quan sống cùng nhau? Có vẻ như những thứ gây tranh cãi.

Hibernate không bao giờ khóa các đối tượng trong bộ nhớ và luôn sử dụng cơ chế khóa của cơ sở dữ liệu. Ngoài ra, "nếu chế độ khóa yêu cầu không được hỗ trợ bởi cơ sở dữ liệu, Hibernate sử dụng một chế độ thay thế thích hợp thay vì ném một ngoại lệ. Điều này đảm bảo rằng các ứng dụng được di động." Nó có nghĩa là, nếu cơ sở dữ liệu của bạn không hỗ trợ SELECT ... CẬP NHẬT, có lẽ, bạn sẽ nhận được những ngoại lệ này.

Một lý do khác có thể là bạn chưa sử dụng "org.hibernate.annotations.CascadeType.LOCK" cho trẻ em.

+0

Tôi đang sử dụng MySQL InnoDB hỗ trợ "CHỌN ... CHO CẬP NHẬT", vì vậy tôi không thấy vấn đề ở đây. Hơn nữa, tôi cũng đang khóa lạc quan, để có được một "thông báo" khi một sửa đổi đồng thời được thực hiện. – Erik

+0

Xin lỗi, đã bỏ lỡ điểm bạn gặp vấn đề với trẻ em (được in đậm :)). Tôi đã cập nhật câu trả lời ... – Stas

+0

Trong mã của tôi, tôi luôn luôn khóa trên thực thể, ngay cả khi tôi chỉ muốn cập nhật các thực thể không phải là trẻ em. Vì vậy, cũng nên có khóa mua lại. Quan tâm chính của tôi là tôi không làm việc với thực thể/trẻ em mới nhất bằng cách chỉ sử dụng làm mới. – Erik

1

Bạn có thể muốn xem xét Hibernate-Sự cố này: LockMode.Upgrade doesn't refresh entity values.

Tóm lại: Hibernat KHÔNG thực hiện lựa chọn sau khi khóa thành công nếu thực thể đã được tải sẵn. Bạn cần phải gọi làm mới cho thực thể cho chính mình sau khi bạn nhận được khóa.

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