Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在事务启动之前或提交之前执行操作?_Java_Spring_Spring Boot_Jpa_Spring Transactions - Fatal编程技术网

Java 如何在事务启动之前或提交之前执行操作?

Java 如何在事务启动之前或提交之前执行操作?,java,spring,spring-boot,jpa,spring-transactions,Java,Spring,Spring Boot,Jpa,Spring Transactions,在事务提交之前,我必须在特殊类型中执行插入 这是由于较旧的数据库设计使用此表在每个业务表上使用触发器执行审核操作。另一个用C编写的软件使用此模式执行审计,对代码的影响较小: 建立连接时,在临时表中插入审核数据 执行各种插入/更新,触发器将这些操作与审核数据链接 提交:从临时表中刷新审核日期 现在我有了一个SpringBoot+JPA(Hibernate)应用程序,它开始使用同一个数据库,我需要重现这个模式。 然而,对于事务的Spring+JPA抽象,我很难找到复制这种行为的方法 我需要在创建

在事务提交之前,我必须在特殊类型中执行插入

这是由于较旧的数据库设计使用此表在每个业务表上使用触发器执行审核操作。另一个用C编写的软件使用此模式执行审计,对代码的影响较小:

  • 建立连接时,在临时表中插入审核数据
  • 执行各种插入/更新,触发器将这些操作与审核数据链接
  • 提交:从临时表中刷新审核日期
现在我有了一个SpringBoot+JPA(Hibernate)应用程序,它开始使用同一个数据库,我需要重现这个模式。 然而,对于事务的Spring+JPA抽象,我很难找到复制这种行为的方法

我需要在创建事务时(或在提交事务之前)插入审计数据。 我已经检查了这一点,但看起来我必须在每个服务中声明发布者并手动触发事件,如:

正如您在本示例中看到的,服务声明了一个
ApplicationEventPublisher
,需要调用
ApplicationEventPublisher.publishEvent(事件)每次更新/插入后

这并不能满足我的需要:我确实需要能够在每次提交()之前执行此操作,并且对于所有服务和存储库来说,这必须是自动的

我已经开始研究一个基于AOP的解决方案,但我觉得这太过分了


那么,在Spring Boot+JAP上下文中,是否有任何简单的解决方案可以在任何提交之前执行某些操作?

JPA为您提供了事件侦听器工具

您可以使用@EntityListener(YourListener.class)注释标记实体:

@Entity
@EntityListeners(YourListener.class)
...
public class Entity implements Persistable<>
@实体
@EntityListeners(YourListener.class)
...
公共类实体实现持久化
你的听众应该是这样的:

public class YourListener<T extends Persistable> {
    @PostUpdate
    public void onPostPersist(T entity) {
        //do
    }
}
公共类YourListener{
@假想
PostPersist上的公共无效(T实体){
//做
}
}
要标记侦听器的方法,您可以选择以下挂钩:@(prepersists/PreUpdate/PreRemove/postersists/postpdate/PostRemove/PostLoad)

确保在执行侦听器期间,不要使用同一个EntityManager来节省任何额外的开销!请看这里的答案和其他答案


我个人最后启动了新的Hibernate会话,以防我需要将数据保存到另一个实体中。

您是否尝试过@EventListener(Customer.class)@TransactionalEventListener(phase=TransactionPhase.BEFORE\u COMMIT)假设您正在使用Hibernate编写一个Hibernate EventListener或拦截器,并在其中执行此操作。不要与SpringEventListeners和Interceptor或AOP混淆。或者,作为最后一种手段,您可以始终为
平台TransactionManager
创建一个包装器,并在委托给实际的事务管理器之前在其中进行包装。@Ganesh问题是,我想要一个完全自动化的系统,而不是在我的所有服务上添加事件发布器。您是否有这样一个以自动化方式使用TransactionalEventListener的示例?@Deinum,感谢您的提示,Hibernate拦截器看起来是一个很好的候选者,我将尝试找出如何为我的项目设置一个拦截器!这种方法的问题是每次刷新实体时都会调用一次自定义预持久化操作。这可能是一项有趣的工作,但不是最有效的。
public class YourListener<T extends Persistable> {
    @PostUpdate
    public void onPostPersist(T entity) {
        //do
    }
}