首页 > 解决方案 > TransactionRequiredException:没有可用于当前线程的具有实际事务的 EntityManager - 无法可靠地处理“合并”调用

问题描述

我们有一些旧的 spring 应用程序,其中我们有一些 spring-boot 注释。我有一个场景,我想使用 EntityManager 执行合并,但这会引发“javax.persistence.TransactionRequiredException:没有 EntityManager 与当前线程的实际事务可用 - 无法可靠地处理‘合并’调用”异常。我已经尝试过其他帖子中可用的解决方案,例如在 upload() 方法级别上使用 javax.persistent @Trasactional 注释,但没有任何效果。这些是我正在使用的类 -

ApplicationContextProvider.java

@Service
public class ApplicationContextProvider implements ApplicationContextAware {

  private static ApplicationContext context;

  public static ApplicationContext getApplicationContext() {
    return context;
  }

  @Override
  public void setApplicationContext(ApplicationContext ac) throws BeansException {
    context = ac;
  }
}

MyConfigType.java

@Entity
@Table(name = "config_loaded_table")
public class MyConfigType { 
  @Id
  private int id;

  @Column(name = "file_name")
  private String fileName;  

    // getters and setters
}

ConfigUploader.java(抽象类)——

public abstract class ConfigUploader {
    public abstract String upload() throws Exception;
}

我正在使用来自 entityManager 的合并的 ConfigLoader 实现类-

public class MyConfigLoader extends ConfigUploader {

    private int id;
    private String path;

    public MyConfigLoader(int id, String path) {
        this.id= id;
        this.path=path;
    }

    @Override
    public String upload() throws Exception {

        try {
            MyConfigType myConfigType = new MyConfigType();
            myConfigType.setFileName("employee.config");

            // at this line I am getting exception. 
            int id = ApplicationContextProvider.getApplicationContext().getBean(EntityManager.class).merge(myConfigType).getId();
            myConfigType.setId(id);

        }catch (Exception e) {
            // getting javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call
           log.error(e); 
        }
    }
}

最后,我调用 ConfigLoader 实现的 upload() 方法的主类 -

public class ConfigThread implements Runnable {

    @Override
    public void run() {

        ConfigUploader configLoader = new MyConfigLoader(id,path);
        configLoader.upload(); // calling upload() method here

    }
}

标签: springspring-bootentitymanagerjavax.persistence

解决方案


不幸的是,你的类不是spring组件,所以这里不能使用@Transactional。你可以尝试这样的事情:

EntityManager entityManager = ApplicationContextProvider.getApplicationContext().getBean(EntityManager.class);
entityManager.getTransaction().begin();
entityManager.merge(...);
entityManager.getTransaction().commit();

推荐阅读