java - 更新时发生 TransactionRequiredException

标签 java spring jpa entitymanager

我在日志中收到异常:

javax.persistence.TransactionRequiredException: Executing an update/delete query

这位于 updateSomething() 方法的 isNew = false 分支中。我没有发现其他分支的异常。

我在 stackoverflow 上发现了一些关于使用 entityManager.joinTransaction(); 的内容,但是当我这样做时,我得到了另一个异常:

java.lang.IllegalStateException: Not allowed to join transaction on shared EntityManager

我想正确处理这个问题,以便 updateSomething 方法起作用。我还想知道嵌套 @Transactional 注释是否是一个好主意,以及从事务方法调用事务方法的效果是什么 - 我相信内部事务在其自己的事务中运行并提交到数据库。

注意:HACK 不起作用,我将其作为我尝试过的示例。

想法:每次更新(使用 native SQL 的更新)后执行 entityManager.flush() 有帮助吗?

@Transactional
public boolean generateLogsComposite() {
    Connection conn = getConnection();
    writeSomeData(conn);//write some data using a separate connection
    boolean isNew = checkSomeData();//The check works with the data from writeSomeData although not using he connection conn
    if(isNew) {
        generateEmail(conn);//Calls a stored procedure on connection conn.
        updateRunEnvOnEmail(emailId, runEnv);
        //Now the data from generateEmail and updateRunEnvOnEmail is present
    } else {
        updateSomething();//has a javax.persistence.TransactionRequiredException: Executing an update/delete query
    }
}

private void joinTransaction() {
    try {
        //HACK vs javax.persistence.TransactionRequiredException: Executing an update/delete query
        entityManager.joinTransaction();
        logger.debug("Joined transaction successfully");
    } catch(Throwable t) {
        //java.lang.IllegalStateException: Not allowed to join transaction on shared EntityManager
    }
}

@Transactional
public void updateRunEnvOnEmail(Long emailId, String runEnv)
{
    try
    {
        //HACK vs javax.persistence.TransactionRequiredException: Executing an update/delete query
        joinTransaction();

        Query query = entityManager
                .createNativeQuery("update XXX.EMAIL e set e.RUN_ENVIRONMENT = :runEnv where e.EMAIL_ID = :emailId");
        query.setParameter("runEnv", runEnv);
        query.setParameter("emailId", emailId);
        query.executeUpdate();
    } catch (Exception e)
    {
        logger.debug("Error while updating RUN_ENVIRONMENT on Email : "
                + emailId + " ::: " + e);
    }

}

@Transactional
public void updateSomething()
{
    try
    {
        //HACK vs javax.persistence.TransactionRequiredException: Executing an update/delete query
        joinTransaction();

        Query query = entityManager
                .createNativeQuery("update something");
        query.executeUpdate();
    } catch (Exception e)
    {
        logger.debug("Error while updating something",e);
    }

}

最佳答案

通常,JPA 不喜欢在事务之外调用更新,除非明确配置这样做。执行此操作的正确方法如下:

entityManager.getTransaction().begin();
// do your updates
entityManager.getTransaction().commit();

但是,如果您希望由 Spring 管理事务(您的 IllegalStateException 建议如此),那么您可能需要查看 @Transactional (但请确保您提供正确的事务管理器,您可能需要查看 TransactionRequiredException Executing an update/delete query 上的答案以获取见解)。

关于java - 更新时发生 TransactionRequiredException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56648290/

相关文章:

java - GRBVar 的绝对值

java - 如何测试Java集合是否支持add操作?

Java Spring MVC 模板项目问题

java - Spring @ResponseBody Json 循环引用

Java 访问者模式

java - UUID.fromString(var) 接受 Java 中的附加字符

spring - @scope 注释的proxyMode 和上下文组件扫描的scoped Proxy 之间的区别。?

java - 新事务是否分离所有以前的实体?

java - 为单个实体禁用 JPA Hibernate 模式验证

java - 连接错误 JPA 和named_queries xml 的预期路径