2014-04-04 14 views
5

Tôi đang sử dụng Hibernate Envers để duy trì lịch sử đối tượng. Tại một số điểm, chúng tôi muốn chụp ảnh chụp nhanh trạng thái đồ thị đối tượng - và chúng tôi có thể thực hiện điều này bằng cách biết bản sửa đổi Envers tương ứng mà chúng tôi lưu trữ trên bản ghi kiểm toán.Làm thế nào để buộc Hibernate Envers cam kết sửa đổi trong một phương pháp Spring @Transactional

Tuy nhiên, chúng tôi gặp sự cố. Đối tượng cha được cập nhật trong cùng một giao dịch mà chúng ta tạo và lưu trữ bản ghi kiểm toán con của nó - hoàn thành với bản sửa đổi Envers. Chúng tôi có thể nhận được phiên bản mới nhất:

Number revision = reader.getRevisionNumberForDate(new Date(Long.MAX_VALUE)); 

hoặc tạo ra một phiên bản mới:

Number revision = reader.getCurrentRevision(DefaultRevisionEntity.class, true).getId(); 

và sử dụng một trong hai, nhưng cam của cha mẹ luôn luôn xảy ra sau đó. Và đó là khi Envers tăng bản sửa đổi. Do đó bản sửa đổi chúng tôi thực sự cần tham khảo trong hồ sơ kiểm toán luôn cao hơn giá trị được lưu trữ. Trong trường hợp đơn giản nhất, chúng tôi nhận và lưu trữ phiên bản N nhưng phiên bản cha mẹ chúng ta cần được lưu giữ như N + 1.

Các tài liệu tham khảo đọc AuditReader có thể thu được với:

JpaTransactionManager transactionManager; // injected 
EntityManagerFactory emf = transactionManager.getEntityManagerFactory(); 
EntityManager entityManager = emf.createEntityManager(); 
AuditReader reader = AuditReaderFactory.get(entityManager); 

Chúng tôi đang sử dụng Spring 3 Chú thích @Transactional và Hibernate 4.2.

đồ thị dưới lớp tối thiểu:

Parent.class 
    int version   // for hibernate optimistic locking 
    String revisionName 
    List<AuditChild> audits 

AuditChild.class 
    int enversRevision // use to retrieve previous graphs of parent 

Tôi đã thử nhiều phương pháp để buộc các cam kết của cha mẹ để xảy ra đầu tiên, trong đó có:

  • Splitting mã trên nhiều phương pháp với @Transactional (propagation = Propagation.REQUIRES_NEW)
  • Yêu cầu rõ ràng về thực thểManager.flush();

Mọi thứ tôi đã thử đều không có hiệu lực hoặc gây ra các sự cố khác. Tôi rất vui khi được nghe về các giải pháp đã làm việc cho người khác. Cảm ơn.

+0

Số sửa đổi phải là duy nhất cho giao dịch, bạn có chắc chắn rằng 'reader.getCurrentRevision (DefaultRevisionEntity.class, true) .getId()' không hoạt động?Bạn cần tham khảo bản sửa đổi "hiện tại" cho giao dịch hiện tại. – adamw

+0

@adamw Có để tạo bản sửa đổi mới. Tuy nhiên khi giao dịch kèm theo của tôi đã được cam kết sửa đổi thực tế trên các hàng cập nhật có liên quan trong * _AUD bảng (s) là> n (n + 1 khi không có bản cập nhật khác để cơ sở dữ liệu chồng chéo lên tx này). Vì vậy, các Id trên đối tượng trả về từ 'getCurrentRevision()' không phải là một áp dụng khi Tx hiện tại đã được cam kết. Công việc của tôi xung quanh là tạo một bản sửa đổi giả (-1) và trong giao dịch thứ 2 để đọc lại và cập nhật tài liệu tham khảo sửa đổi của tôi. (Môi trường: Hibernate Envers 4.2, Spring 3.2 @Transactional các giao dịch được chú thích; DB2 9.1). – user598656

+0

Hmm, tốt nếu bạn gọi getCurrentRevision() trong một TX, bạn sẽ nhận được bản sửa đổi cho giao dịch đó. Bạn có bất kỳ es() es ở giữa? Mặc dù điều đó không quan trọng lắm. – adamw

Trả lời

0

Cách thay thế dễ dàng hơn là sử dụng số @Version.

Đầu tiên, Trình gỡ cài đặt cần phải được định cấu hình để thực sự kiểm tra giá trị của trường khóa lạc quan mà không thực hiện theo mặc định. Bạn thực hiện việc này bằng cách đặt cấu hình sau:

org.hibernate.envers.do_not_audit_optimistic_locking_field=false 

Tại thời điểm này, Envers sẽ bao gồm trường trong bảng lịch sử kiểm tra và sẽ nhân rộng giá trị phiên bản ORM đã gán vào bảng lịch sử kiểm tra. Tại thời điểm này, chúng tôi có một cách duy nhất để tham gia hàng thực thể ORM với hàng lịch sử kiểm tra bằng cách sử dụng @Formula. SQL công thức sẽ là:

SELECT e.REV 
    FROM YourEntity_AUD e 
WHERE e.originalId.id = id 
    AND e.version = version 

Bây giờ nó chỉ đơn giản như thêm một trường để tổ chức của bạn:

@Formula(/* the SQL from above */) 
@NotAudited 
private Integer revisionNumber; 

HTH.

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