如何使用spring data envers查找实体的所有修订版?

ash*_*ram 8 java spring hibernate-envers spring-data-jpa

我在Spring启动应用程序中使用spring-data-envers.我可以成功记录我的实体的审核.

现在,我需要在UI中向用户显示审计数据.就像搜索表单一样,用户可以选择持续时间和实体,以便查看审计日志.

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);
}
Run Code Online (Sandbox Code Playgroud)

如何编写自定义查询以获取特定用户在两个日期之间对实体的所有修订.

请注意,我在user_rev_entity表中添加了其他列,用于存储用户ID和修改日期.如果我将此表与entity_aud表连接,我可以得到结果.

以下是我的Audit表的脚本.

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
Run Code Online (Sandbox Code Playgroud)

因此,基本上我正在寻找特定用户在特定时间内为实体说出的所有更改.

会有更多这样的实体.

Dan*_*oie 5

Spring Data Envers 不支持像您在 spring data 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());
}
Run Code Online (Sandbox Code Playgroud)

这不是一个完美的选择,因为您将从数据库中获取所有修订。然而,这是保持数据库抽象的最简单方法。

否则,您必须跳过 Spring Data Envers 并使用 Envers API。

祝你好运,问候

  • *不是一个完美的选择,因为您将从数据库中获取所有修订*。我想你可以说两次,历史表应该是数据库中最重的,这绝对是你不想进行后过滤的。 (3认同)

hei*_*don 5

您看过AuditReaderFactory和 AuditReader 吗?

查看 AuditReader 的createQuery的文档:

与此 AuditReader 实例关联的查询创建器,可以使用它创建查询并稍后执行。

这会返回一个 AuditQueryCreator,您可以使用它来创建查询,如下所示:

AuditQuery query = getAuditReader().createQuery()
.forRevisionsOfEntity(MyEntity.class, false, true);
Run Code Online (Sandbox Code Playgroud)

forRevisionsOfEntity 有几个选项,请参阅AuditQueryCreator文档。

该查询应允许您使用AuditCriterion选择特定修订

Hibernate 包含与此相关的文档: 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 和 hibernate 标准经验,所以这可能不正确,但也许它会帮助你开始。

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();
Run Code Online (Sandbox Code Playgroud)