java - 如何在事务开始之前或提交之前执行操作?

标签 java spring spring-boot jpa spring-transactions

我必须在特殊的 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/

相关文章:

java - 用于存储列标题/标签的 Oracle 元数据

Spring Boot @JsonIgnore 在实体上,有时我希望一个属性作为 Json 返回

spring-boot - Spring Boot RestController 不返回 JSON 数据

java - 无法在 spring 中处理配置类的导入候选

java - 如何在契约提供者 JUnit 测试中传递多个消费者名称

java - 更改默认 Maven 路径?

java - 沉浸模式下的全屏应用程序

java - 宾果游戏 Java

java - spring-security 访问被拒绝异常

Spring 查找方法和作用域代理的使用