我必须在特殊的 global temporary table 中执行插入操作在事务提交之前。
这是由于数据库的设计较旧,该数据库使用此表通过每个业务表上的触发器来执行审计操作。另一个用 C 编写的软件使用这种模式来执行审计,对代码的影响很小:
- 建立连接时将审核数据插入临时表
- 执行各种插入/更新,触发器会将这些操作与审计数据链接起来
- 提交:审核日期从临时表中刷新
现在我有一个 Spring Boot + JPA (Hibernate) 应用程序,它开始使用相同的数据库,我需要重现此模式。 然而,通过 Spring + JPA 的事务抽象,我很难找到一种方法来复制这种行为。
我需要在创建事务时(或在提交事务之前)执行审计数据的插入。 我检查过这个有前途的TransactionalEventListener ,但看起来我必须声明一个发布者并在每个服务中手动触发事件,就像 following example 中那样:
@Service
public class CustomerService {
private final CustomerRepository customerRepository;
private final ApplicationEventPublisher applicationEventPublisher;
public CustomerService(CustomerRepository customerRepository, ApplicationEventPublisher applicationEventPublisher) {
this.customerRepository = customerRepository;
this.applicationEventPublisher = applicationEventPublisher;
}
@Transactional
public Customer createCustomer(String name, String email) {
final Customer newCustomer = customerRepository.save(new Customer(name, email));
final CustomerCreatedEvent event = new CustomerCreatedEvent(newCustomer);
applicationEventPublisher.publishEvent(event);
return newCustomer;
}
}
正如您在此示例中所看到的,服务声明一个 ApplicationEventPublisher
并需要在每次更新/插入后调用 applicationEventPublisher.publishEvent(event);
。
这不能满足我的需求:我确实需要能够在每次 commit() 之前执行此操作,并且这对于所有服务和存储库必须是自动的。
我已经开始研究基于 AOP 的解决方案,但我觉得它有点矫枉过正。
那么有没有什么简单的解决方案可以在 Spring Boot + JAP 上下文中的任何提交之前执行一些操作?
最佳答案
JPA为您提供了事件监听工具。
您可以使用 @EntityListener(YourListener.class) 注解标记您的实体:
@Entity
@EntityListeners(YourListener.class)
...
public class Entity implements Persistable<>
你的监听器应该是这样的:
public class YourListener<T extends Persistable> {
@PostUpdate
public void onPostPersist(T entity) {
//do
}
}
有several annotations要标记监听器的方法,您可以选择以下钩子(Hook):@(PrePersits/PreUpdate/PreRemove/PostPersits/PostUpdate/PostRemove/PostLoad)。
确保在执行监听器期间不使用相同的 EntityManager 来节省任何额外费用!请参阅https://stackoverflow.com/a/42222592/5661496以及其他答案。
我个人最终启动了新的 Hibernate session ,以防我需要将数据保存在另一个实体中。
关于java - 如何在事务开始之前或提交之前执行操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58913830/