在我的应用程序中,我需要检索每个事务的新,更新和删除实体的列表。像这样:
// useful functionality
@Transactional
public void createNewBlogPost(int userId, String title, String text) {
Post post = new Post();
post.title = title; // "hello"
post.text = text; // "there"
postRepository.save(post);
// more work with JPA repositories here
}
...
// gets called right after createNewBlogPost()
public void onTransaction(UnitOfWork uow) {
List<?> newEntities = uow.getNewEntities();
assertEquals(1, newEntities.size()); // 1 new entity
Object firstNewEntity = newEntities.get(0);
assertTrue(firstNewEntity instanceof Post); // this new entity
// is a Post
Post newPost = (Post)firstNewEntity;
assertEquals("hello", newPost.title);
assertEquals("there", newPost.text);
}
我设法找到的最相关的东西是Spring提供的审核功能,其中包含@CreatedBy
,@CreatedDate
,@LastModifiedBy
,@LastModifiedDate
等注释。虽然它在技术上非常接近,但它并不是我想要实现的目标。
Spring Data JPA是否提供了一种机制来检索每个单个事务的数据更改?
答案 0 :(得分:1)
由于您的用例是Hibernate和JPA特定的,因此您应该查看Hibernate Envers和Spring Data Envers。他们可能会给你一些想法,但要小心:项目本身,我不确定他们是否活跃。
答案 1 :(得分:0)
我花了一些时间进行研究,并设法找到一个相对简单的Hibernate特定解决方案。基本上有两个问题需要解决:
要解决第1页问题,可以使用EventListenerRegistry
。这是一个例子:
@Component
public class HibernateListenersConfigurer {
@Autowired
private EntityManagerFactory entityManagerFactory;
@Autowired
private HibernateListeners hibernateListeners;
@PostConstruct
public void init() {
HibernateEntityManagerFactory hibernateEntityManagerFactory =
(HibernateEntityManagerFactory)entityManagerFactory;
SessionFactoryImpl sessionFactoryImpl =
(SessionFactoryImpl)hibernateEntityManagerFactory.getSessionFactory();
EventListenerRegistry eventListenerRegistry = sessionFactoryImpl.
getServiceRegistry().
getService(EventListenerRegistry.class);
eventListenerRegistry.appendListeners(EventType.PRE_INSERT, hibernateListeners);
eventListenerRegistry.appendListeners(EventType.PRE_UPDATE, hibernateListeners);
eventListenerRegistry.appendListeners(EventType.PRE_DELETE, hibernateListeners);
}
}
hibernateListeners
对象获取所有这些事件,并且可以执行审计它们所需的任何操作。这是一个例子:
@Component
public class HibernateListeners implements
PreInsertEventListener,
PreUpdateEventListener,
PreDeleteEventListener {
@Autowired
private ChangeTracker changeTracker;
@Override
public boolean onPreInsert(PreInsertEvent event) {
// event has a bunch of relevant details
changeTracker.trackChange(event);
return false;
}
...other listeners here...
然后,为了解决p.2,上面看到的changeTracker
是一个请求范围的bean:
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ChangeTracker {
// a sort of "Unit of Work"
private List<Change> changes = new ArrayList<Change>();
public void trackChange(PreInsertEvent event) {
changes.add(makeChangeFromEvent(event));
}
public void handleChanges() {
// Do whatever needed :-)
}
}
然后,在请求处理完成后,几乎没有可用的选项可以最终调用handleChanges()
:手动调用它,使用HandlerInterceptor
,使用过滤器,使用AOP。 HandlerInterceptor
和过滤器不是很好,因为在我的情况下,它们在响应已经发送到客户端后被调用,这导致“业务数据”和“更改数据”之间的不一致。我最终切换到AOP,似乎工作正常。
这是一个游乐场:https://github.com/loki2302/spring-change-tracking-experiment