我在spring boot应用程序中使用了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);
}如何编写自定义查询,以获取特定用户在两个日期之间对某个实体的所有修订。
注意,我已经向存储用户id和修改日期的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因此,基本上我是在寻找特定用户在特定时间内对某个实体所做的所有更改。
将会有更多这样的实体。
发布于 2016-03-27 02:00:31
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());
}这不是一个完美的匹配,因为您将从数据库中获取所有修订。但是,这是从数据库中保留抽象的最简单方法。
否则,您必须跳过Spring数据Envers,而使用Envers API。
祝你好运,致敬
发布于 2016-03-27 06:08:33
你看过AuditReaderFactory和AuditReader吗?
查看AuditReader的createQuery文档
与此AuditReader实例关联的查询创建者,可用于创建查询并在以后执行查询。
这将返回一个AuditQueryCreator,您可以使用该use创建如下查询:
AuditQuery query = getAuditReader().createQuery()
.forRevisionsOfEntity(MyEntity.class, false, true);forRevisionsOfEntity有几个选项,请参阅AuditQueryCreator文档。
该查询应允许您使用AuditCriterion选择特定修订
与此相关的Hibernate envers文档:http://docs.jboss.org/hibernate/orm/5.0/userGuide/en-US/html_single/#revisions-of-entity
您可以使用与前一个查询相同的方式向此查询添加约束。还有一些额外的可能性:
使您可以如上所述地访问修订的类型(添加、修改、删除)。
编辑我尝试了一个实际的解决方案。我几乎没有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();发布于 2019-02-15 04:37:50
要获得所有修订,您可以简单地执行以下操作:
AuditQuery query = auditReader.createQuery().forRevisionsOfEntity(MyEntity.class, false, false);
List<Object[]> result = query.getResultList();
// and loop over the result list
for (Object[] tuple : result) {Item item = (Item) tuple[0];}https://stackoverflow.com/questions/36008394
复制相似问题