Java JPA:如何使用JTA EntityManager的事务?

Java JPA:如何使用JTA EntityManager的事务?,java,transactions,jpa-2.0,entitymanager,jta,Java,Transactions,Jpa 2.0,Entitymanager,Jta,首先,解决方案对我来说是没有选择的,因为我不能更改持久性单元 我的问题是我使用JTA EntityManager,但我只需要一个用例,比如事务: public boolean saveWithResult(PointsValidityPeriod pointsValidityPeriod) { //TODO use transaction here super.save(pointsValidityPeriod); if (updatePrevious(pointsV

首先,解决方案对我来说是没有选择的,因为我不能更改持久性单元

我的问题是我使用JTA EntityManager,但我只需要一个用例,比如事务:

public boolean saveWithResult(PointsValidityPeriod pointsValidityPeriod)
{
    //TODO use transaction here 
    super.save(pointsValidityPeriod);

    if (updatePrevious(pointsValidityPeriod.getValidFrom()) != 1)
    {
        logger.error("Update of Period was not possible, because UPDATE returned no single result.");

        return false;
    }

    pointsValidityPeriodEvent.fire(pointsValidityPeriod);

    return true;
}
保存方法(我无法更改):

public void save(T entity)
{
    getEntityManager().persist(entity);
}

您可以看到,有一个save调用,但是如果更新出错,必须回滚这个save,那么我如何实现呢?有什么想法吗?

这取决于你的方法。如果没有,则默认情况下,事务边界设置为业务方法,如JB所指出的

因此,整个方法是一个事务。通常情况下,
save
方法的事务管理很重要(如果
REQUIRED
REQUIRES\u NEW
,则会有所不同),但在这种情况下,您进行的是本地方法调用,而不是业务方法调用,因此
save
方法的任何事务管理设置在这里都不适用

因此,如果
更新
失败,您可以基于自动事务回滚(如果是生成回滚发送的异常的EntityManager调用),也可以手动插入
会话上下文
并在其上调用
setRollbackOnly()
,行与行之间的内容:

@Resource
SessionContext ctx;

public boolean saveWithResult(PointsValidityPeriod pointsValidityPeriod)
{
   // ...
    if (updatePrevious(pointsValidityPeriod.getValidFrom()) != 1)
    {
        // ...
        ctx.setRollbackOnly();
        // ...
    }
}

这完全取决于您的方法和事务注释。如果没有,则默认情况下,事务边界设置为业务方法,如JB所指出的

因此,整个方法是一个事务。通常情况下,
save
方法的事务管理很重要(如果
REQUIRED
REQUIRES\u NEW
,则会有所不同),但在这种情况下,您进行的是本地方法调用,而不是业务方法调用,因此
save
方法的任何事务管理设置在这里都不适用

因此,如果
更新
失败,您可以基于自动事务回滚(如果是生成回滚发送的异常的EntityManager调用),也可以手动插入
会话上下文
并在其上调用
setRollbackOnly()
,行与行之间的内容:

@Resource
SessionContext ctx;

public boolean saveWithResult(PointsValidityPeriod pointsValidityPeriod)
{
   // ...
    if (updatePrevious(pointsValidityPeriod.getValidFrom()) != 1)
    {
        // ...
        ctx.setRollbackOnly();
        // ...
    }
}

我有解决办法,但我不知道为什么会这样。也许有人能给我解释一下。 在我的backingbean中有save方法。有两个实体。getEntity()是支持bean使用的当前实体,currentValidityPeriod是该实体的另一个实例,它保存该实体的最新数据库状态,由currentValidityPeriod=pointsValidityService.findCurrent()获取;findCurrent()只是一个执行TypedQuery的方法:

public PointsValidityPeriod findCurrent()
{
    TypedQuery<PointsValidityPeriod> validityPeriodQuery = entityManager.createNamedQuery(PointsValidityPeriod.FindCurrent, PointsValidityPeriod.class);

    return validityPeriodQuery.getSingleResult();
}
这是将被调用的服务方法:

@Override
public void save(PointsValidityPeriod pointsValidityPeriod)
{
    super.save(pointsValidityPeriod);
}
…和超类的保存方法:

public void save(T entity)
{
    getEntityManager().persist(entity);
}

为什么实体管理器保存新实体并更新旧实体?我只是将一个实体传递给实体管理器。虽然这是预期的行为,但我想知道为什么会这样。

我有解决方案,但我不知道为什么会这样。也许有人能给我解释一下。 在我的backingbean中有save方法。有两个实体。getEntity()是支持bean使用的当前实体,currentValidityPeriod是该实体的另一个实例,它保存该实体的最新数据库状态,由currentValidityPeriod=pointsValidityService.findCurrent()获取;findCurrent()只是一个执行TypedQuery的方法:

public PointsValidityPeriod findCurrent()
{
    TypedQuery<PointsValidityPeriod> validityPeriodQuery = entityManager.createNamedQuery(PointsValidityPeriod.FindCurrent, PointsValidityPeriod.class);

    return validityPeriodQuery.getSingleResult();
}
这是将被调用的服务方法:

@Override
public void save(PointsValidityPeriod pointsValidityPeriod)
{
    super.save(pointsValidityPeriod);
}
…和超类的保存方法:

public void save(T entity)
{
    getEntityManager().persist(entity);
}

为什么实体管理器保存新实体并更新旧实体?我只是将一个实体传递给实体管理器。虽然这是预期的行为,但我想知道为什么会这样。

JTA的全部要点是管理事务。您在哪个环境中执行应用程序?使用ejb的应用服务器?然后使用EJB来划分事务:这是它们的要点。EJB在默认情况下是事务性的。默认情况下,EJB方法中的所有代码都在事务中执行。如果我在saveWithResult方法中说
If(updatePrevious()==2){=>不要调用save.}
,那么updatePrevious将不会回滚,因此执行了更新,但插入(save)没有,那么这是如何进行事务处理的呢?我不明白。JTA的全部目的是管理交易。您在哪个环境中执行应用程序?使用ejb的应用服务器?然后使用EJB来划分事务:这是它们的要点。EJB在默认情况下是事务性的。默认情况下,EJB方法中的所有代码都在事务中执行。如果我在saveWithResult方法中说
If(updatePrevious()==2){=>不要调用save.}
,那么updatePrevious将不会回滚,因此执行了更新,但插入(save)没有,那么这是如何进行事务处理的呢?我不明白。不幸的是,我不能这样做。Eclipse向我展示了“没有任何bean符合注入点[JSR-299§5.2.1]的条件”,最后,它在注入点[[field]处启动JBoss:org.JBoss.weld.exceptions.DeploymentException:weld-001408类型[SessionContext]的未满足的依赖项时导致异常@injection注释不应该是@Resource吗?有关如何从EJB获取SessionContext的信息,请参阅。啊,当然是JB-
@Resource
!对不起,伙计们,太多CDI会让我变傻!不幸的是,我不能这样做。Eclipse向我显示“没有任何bean可以被注入到注入点[JSR-299§5.2.1]”最后,在启动JBoss:org.JBoss.weld.exceptions.DeploymentException:weld-001408时,它会导致异常,类型[SessionContext]的依赖项在注入点[[field]@injection]处带有限定符[@Default]。注释不应该是@Resource吗?有关如何获取SessionContex的信息,请参阅