2016-03-15 157 views
5

我在我的spring啓動應用程序中使用spring-data-envers。我可以成功地在我的實體上記錄審覈。如何使用spring數據envers查找實體的所有修訂版本?

現在,我需要在用戶界面中向用戶顯示審計數據。就像會有搜索表單一樣,用戶可以選擇他想要查看審計日誌的持續時間和實體。

由string-data-envers提供的RevisionRepository只有三個方法,如下所示。

@NoRepositoryBean 
public interface RevisionRepository<T, ID extends Serializable, N extends Number & Comparable<N>> { 

    /** 
    * Returns the revision of the entity it was last changed in. 
    * 
    * @param id must not be {@literal null}. 
    * @return 
    */ 
    Revision<N, T> findLastChangeRevision(ID id); 

    /** 
    * Returns all {@link Revisions} of an entity with the given id. 
    * 
    * @param id must not be {@literal null}. 
    * @return 
    */ 
    Revisions<N, T> findRevisions(ID id); 

    /** 
    * Returns a {@link Page} of revisions for the entity with the given id. 
    * 
    * @param id must not be {@literal null}. 
    * @param pageable 
    * @return 
    */ 
    Page<Revision<N, T>> findRevisions(ID id, Pageable pageable); 
} 

如何編寫自定義查詢以獲取特定用戶在兩個日期之間的實體的所有修訂。

請注意,我已將其他列添加到user_rev_entity表中,其中存儲了用戶標識和修改日期。如果我將這張表加入entity_aud表,我可以得到結果。

下面是我的審計表的腳本。

CREATE TABLE `user_rev_entity` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `timestamp` bigint(20) NOT NULL, 
    `created_by` bigint(20) NOT NULL, 
    `created_date` datetime NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 

CREATE TABLE `revchanges` (
    `rev` int(11) NOT NULL, 
    `entityname` varchar(255) DEFAULT NULL, 
    KEY `FK_et6b2lrkqkab5mhvxkv861n8h` (`rev`), 
    CONSTRAINT `FK_et6b2lrkqkab5mhvxkv861n8h` FOREIGN KEY (`rev`) REFERENCES `user_rev_entity` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

CREATE TABLE `roles_aud` (
    `role_id` bigint(20) NOT NULL, 
    `rev` int(11) NOT NULL, 
    `revtype` tinyint(4) DEFAULT NULL, 
    `description` varchar(255) DEFAULT NULL, 
    `description_mod` bit(1) DEFAULT NULL, 
    `display_name` varchar(255) DEFAULT NULL, 
    `display_name_mod` bit(1) DEFAULT NULL, 
    `is_enabled` bit(1) DEFAULT NULL, 
    `enabled_mod` bit(1) DEFAULT NULL, 
    `title` varchar(255) DEFAULT NULL, 
    `title_mod` bit(1) DEFAULT NULL, 
    PRIMARY KEY (`role_id`,`rev`), 
    KEY `FK_pkqm51vsc35w2axvnns4bpas9` (`rev`), 
    CONSTRAINT `FK_pkqm51vsc35w2axvnns4bpas9` FOREIGN KEY (`rev`) REFERENCES `user_rev_entity` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

所以,基本上我在找一個實體在特定時間特定用戶的所有更改說角色。

會有很多這樣的實體。

回答

1

Spring Data Envers不支持自定義查詢,就像您在春季數據jpa中使用的一樣。它所做的只是提供方便的RevisionRepository接口。

但是,您可以做的是使用Revisions<N, T> findRevisions(ID id)方法並從您的服務層應用過濾器。這是一個例子。

@Service 
public UserService { 
    @Resource 
    private UserRepository userRepository; 

    public List<Revision<Integer, User>> findRevisionsBetweenDates(int id, Date startDate, Date endDate){ 
     return userRepository.findRevisions(id).getContent().stream().filter(
      revision -> revision.getEntity().getCreatedDate().getTime() > startDate.getTime() && 
       revision.getEntity().getCreatedDate().getTime() < endDate.getTime() 
     ).collect(Collectors.toList()); 
} 

這不是一個完美的結合,因爲您會從數據庫中獲取所有修訂。但是,它是保持數據庫抽象的最簡單的方法。

否則,您必須跳過Spring Data Envers並使用Envers API。

祝你好運, 問候

+0

*不是一個完美的結合,因爲你將獲取所有來自數據庫的修訂*將失敗。我想你可以說兩次,歷史表應該是數據庫中最重的,這在這裏肯定是你不想過濾的。 – Walfrat

1

你有沒有看AuditReaderFactory和AuditReader?

檢查出AuditReader的createQuery的文檔:這個AuditReader例如,與查詢可以創建並在以後執行相關

查詢的創造者。

返回一個AuditQueryCreator,你可以用它來創建一個查詢,如下所示:

AuditQuery query = getAuditReader().createQuery() 
.forRevisionsOfEntity(MyEntity.class, false, true); 

有用於forRevisionsOfEntity幾個選項,見AuditQueryCreator文檔。

查詢應允許您使用與此AuditCriterion

休眠envers的文檔,選擇特定修訂: http://docs.jboss.org/hibernate/orm/5.0/userGuide/en-US/html_single/#revisions-of-entity

您可以以同樣的方式作爲對前一個添加約束來此查詢。還有一些附加的可能性:

  1. 使用AuditEntity.revisionNumber(),您可以指定約束條件, 預測和訂單上的版本號,在被審計單位 修改
  2. 同樣,使用 AuditEntity.revisionProperty (propertyName),您可以指定 約束,預測和修訂 實體的屬性的訂單,對應於被審計實體 已被修改的修訂
  3. AuditEntity.revisionType()爲您提供訪問如上所述 修訂版的類型(ADD,MOD,DEL)。

編輯 我給在一個實際的解決方案了一槍。我有一點envers和休眠標準的經驗,所以這可能是不正確的,但也許它會幫助你開始。

AuditQuery query = getAuditReader().createQuery() 
     .forRevisionsOfEntity(MyEntity.class, false, true); 

query.add(AuditEntity.revisionProperty("createdDate").gt(minDate)) 
     .add(AuditEntity.revisionProperty("createdDate").lt(maxDate)) 
     .add(AuditEntity.revisionProperty("createdBy").eq(userId)); 

//the documentation shows getSingleResult returns a number 
//so i'm guessing a resultList also contains numbers 
List<Number> resultList = query.getResultList(); 
1

還有一個問題是,findRevisions方法在內部使用SQL IN子句,如果記錄超過999

相關問題