2012-02-06 28 views
8

Môi trường:Cách đặt thủ công các trường @Version với Hibernate 4?

tôi có mà User thực thể:

@Entity 
public class User implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer userId; 

    @Version 
    @Temporal(TemporalType.TIMESTAMP) 
    @Column(name = "VERSION", length = 19) 
    private Date version; 

    @Column(nullable = false, length = 20) 
    private String login; 

    // Getters and Setters 
} 

Tôi có một trang tìm kiếm trong đó liệt kê người dùng, sau đó tôi click vào một người dùng để chỉnh sửa nó (cho nó userId trong URL).

Trong hình thức chỉnh sửa, tôi lưu trữ trên máy chủ các lĩnh vực tổ chức đó và khi tôi tiết kiệm tài của tôi, tôi làm điều này:

User user = entityManager.find(User.class, userId) 
user.setLogin(form.getLogin()); 
user.setVersion(form.getVersion()); 
user.setUserId(form.getUserId()); 
entityManager.merge(user); 

Câu hỏi:

Vì vậy, nếu tôi một cách chính xác hiểu lạc khóa với Hibernate, nếu tôi mở 2 tab trong trình duyệt để chỉnh sửa cùng một người dùng, hãy sau đó cập nhật thông tin đăng nhập trên tab đầu tiên và rồi thông tin đăng nhập trên tab thứ hai, tôi cần có OptimisticLockException sho uldn't I?

Thực tế, đây không phải là trường hợp trên đơn đăng ký của tôi ... Tôi đã xác minh, số form.getVersion() trả về cùng giá trị trong cả hai trường hợp, ngay cả khi trong bản cập nhật thứ hai, user.version đã được cập nhật lần đầu tiên.

Tôi có thiếu gì đó không?

EntityManager được sản xuất @RequestScoped (vì vậy tôi đang ở hai khác nhau EntityManager giây khi tôi cố hợp nhất ...).

Tôi đã cố gắng thực hiện entityManager.lock(user, LockModeType.OPTIMISTIC_FORCE_INCREMENT) trước entityManager.merge(...) (as said here), nhưng không hiệu quả.

Tôi đang sử dụng Seam 3 với JBoss 7.0.2.Final (sử dụng Hibernate 4).

+0

Bạn có chắc chắn thực thểManager bị xóa (hoặc giao dịch được cam kết) không? Truy vấn cập nhật SQL được tạo ra là gì? –

+0

Có, với [kích hoạt việc bán phá giá SQL Hibernate] (http://stackoverflow.com/questions/9159752/how-to-get-jdbc-binding-parameters-from-hibernate-in-jboss-7) Tôi có thể thấy bản cập nhật SQL và liên kết trường JDBC 'version' không tương ứng với' phiên bản' mà tôi đặt trong 'Người dùng' trong' WHERE id =? AND version =? '... Tôi đã phát triển một' FlushInterceptor' được gọi sau khi hàm 'update' tồn tại và thực hiện một' entityManager.flush() '. –

Trả lời

4

Thực ra tôi đã tìm được cách để làm điều đó ... nhưng tôi nghĩ nó không thực sự hiệu quả (vì có thêm 1 yêu cầu SELECT).

User user = entityManager.find(User.class, userId) 
user.setLogin(form.getLogin()); 
user.setVersion(form.getVersion()); 
user.setUserId(form.getUserId()); 

entityManager.detach(user); 
entityManager.merge(user); 

Với entityManager.detach(user), hibernate bây giờ sử dụng giá trị setted version của tôi thay vì riêng giá trị sao chép ở đâu đó của mình ...

5

tôi chỉ làm một số nghiên cứu thêm về vấn đề này.

Nó được không được phép sửa đổi lĩnh vực phiên bản theo spec JPA:

JPA 2.0 cuối cùng Spec, Mục 3.4.2:

Một thực thể có thể truy cập vào trạng thái của phiên bản của nó trường hoặc thuộc tính hoặc xuất một phương thức để ứng dụng sử dụng để truy cập phiên bản, nhưng không được sửa đổi giá trị phiên bản. Với ngoại lệ được ghi chú trong phần 4.10, chỉ nhà cung cấp kiên trì mới được phép đặt hoặc cập nhật giá trị thuộc tính phiên bản trong đối tượng.

Lưu ý: Mục 4.10 đề cập đến cập nhật hàng loạt bỏ qua thuộc tính phiên bản.

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