Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.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 当我添加@Async时,entityManager.flush()将引发异常_Java_Spring_Hibernate_Transactions - Fatal编程技术网

Java 当我添加@Async时,entityManager.flush()将引发异常

Java 当我添加@Async时,entityManager.flush()将引发异常,java,spring,hibernate,transactions,Java,Spring,Hibernate,Transactions,我使用的是Spring框架 我的项目结构是控制器➡️ 服务➡️ 逻辑 我在逻辑类中添加了@Transactional。我正在使用EntityManager执行数据库操作。在每次数据库操作(选择、更新…)之后,我调用entityManager.flush()方法。 一切都很好 但为了提高性能,我在服务类中添加了@Async。 然后,当我调用entityManager.flush()时,会引发一个异常 我调试了源代码,发现EntityManager是通过使用ThreadLocal绑定到线程的,但是当

我使用的是Spring框架

我的项目结构是控制器➡️ 服务➡️ 逻辑

我在逻辑类中添加了
@Transactional
。我正在使用EntityManager执行数据库操作。在每次数据库操作(选择、更新…)之后,我调用
entityManager.flush()
方法。 一切都很好

但为了提高性能,我在服务类中添加了
@Async
。 然后,当我调用
entityManager.flush()
时,会引发一个异常

我调试了源代码,发现EntityManager是通过使用ThreadLocal绑定到线程的,但是当我添加@Async时,会有一个新线程,这个新线程会创建一个新的EntityManager,这没问题。但是当我调用entityManager.flush()时,它将检查事务并调用
JdbcResourceLocalTransactionCoordinatorImpl.isJoin()
方法,
physicalTransactionDelegate
为空,因此将引发异常

physicalTransactionDelegate
在主线程中初始化。

如果要执行entityManager.flush(),应该怎么做?还是我对源头的理解有误

Controller.java

@GetMapping(value = "/getTest", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseDto execute(@Valid final RequestDto requestDto) {
        List<CompletableFuture<Dto>> completableFutures = new ArrayList<>();
        for (ItemRequestDto item : requestDto.getItemRequestDtoList()) {
            completableFutures.add(service.execute(item));
        }
    }
我在github中创建了一个问题。 我找到了解决办法。 只需添加
entityManager.joinTransaction()

我认为这是一个错误

  • 没有@Async
    • 当请求到来时,
      TransactionSynchronizationManager.bindResource((对象键,对象值)
      将被调用,新的EntityManager将绑定到当前线程
    • 然后,调用
      EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactory emf,@Nullable Map properties,boolean synchronizedWithTransaction)
      以获取绑定的EntityManager。在此方法内,它将调用
      EntityManager.joinTransaction()
      。此方法将调用
      JdbcResourceLocalTransactionCoordinatorImpl.getTransactionDriverControl()
      来初始化
      TransactionDriverControlImpl physicalTransactionDelegate
    • 当我们调用
      EntityManager.flush()
      时,将调用jdbResourceLocalTransactionCoordinatorImpl.isjoin()进行检查
  • 使用@Async
    • 当请求到来时,
      TransactionSynchronizationManager.bindResource((对象键,对象值)
      将被调用,新的EntityManager将绑定到当前线程
    • 如果存在@Async,将创建一个新线程
    • 然后,
      EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactory emf,@Nullable Map properties,boolean Synchronized with Transaction)
      被调用以获取绑定的EntityManager。但是在这个新线程中,没有绑定的EntityManager,因此将创建一个新的EntityManager,但是
      EntityManager.joinTransaction()
      将不会被调用。因此将不会初始化
      TransactionDriverControlImpl physicalTransactionDelegate
    • 调用
      EntityManager.flush()
      时。由于
      TransactionDriverControlImpl physicalTransactionDelegate
      为空,将引发异常。
在新线程中创建新的EntityManager时,为什么不调用
EntityManager.jointTransaction()
@GetMapping(value = "/getTest", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseDto execute(@Valid final RequestDto requestDto) {
        List<CompletableFuture<Dto>> completableFutures = new ArrayList<>();
        for (ItemRequestDto item : requestDto.getItemRequestDtoList()) {
            completableFutures.add(service.execute(item));
        }
    }
@Async("taskExecutor")
    public CompletableFuture<InventoryInfoListDto> execute(final ItemRequestDto item) {
        return CompletableFuture.completedFuture(logic.execute(item));
    }
@Transactional(rollbackFor = Throwable.class, timeout = 60)
public ResponseDto execute(final ItemRequestDto item) {
    // process...
}