【问题标题】:TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' callTransactionRequiredException:没有可用于当前线程的具有实际事务的 EntityManager - 无法可靠地处理“合并”调用
【发布时间】:2020-02-06 13:07:25
【问题描述】:

我们有一些旧的 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

    }
}

【问题讨论】:

    标签: spring spring-boot entitymanager javax.persistence


    【解决方案1】:

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

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

    【讨论】:

    • 这是抛出“java.lang.IllegalStateException: 不允许在共享 EntityManager 上创建事务 - 改用 Spring 事务或 EJB CMT”
    • 所以为了让它工作,我必须首先获取 entityManagerFactory 的 bean,然后从中创建 entityManager。即 EntityManagerFactory entityManagerFactory = ApplicationContextProvider.getApplicationContext().getBean(EntityManagerFactory.class); EntityManager entityManager = entityManagerFactory.createEntityManager();
    猜你喜欢
    • 2016-02-20
    • 2017-06-01
    • 2017-09-10
    • 2015-11-23
    • 2017-02-26
    • 2020-09-30
    • 2021-08-10
    相关资源
    最近更新 更多