1

首先,这个解决方案对我来说是没有选择的,因为我无法更改持久性单元。

我的问题是我使用了 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);
}

你看,有一个保存调用,但是如果更新出错,这个保存必须回滚,那么我该如何实现呢?有任何想法吗?

4

2 回答 2

1

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

因此,整个方法是一笔交易。通常,save方法的事务管理很重要(如果是REQUIRED或则不同REQUIRES_NEW),但在这种情况下,您正在进行本地方法调用——而不是业务方法调用,因此方法的任何事务管理设置save都不适用这里。

因此,如果update失败,您可以基于自动事务回滚(如果它是一个 EntityManager 调用,它会生成回滚 Tx 的异常),或者您可以手动注入SessionContext和调用setRollbackOnly()它,两行之间的内容:

@Resource
SessionContext ctx;

public boolean saveWithResult(PointsValidityPeriod pointsValidityPeriod)
{
   // ...
    if (updatePrevious(pointsValidityPeriod.getValidFrom()) != 1)
    {
        // ...
        ctx.setRollbackOnly();
        // ...
    }
}
于 2012-06-27T11:44:20.170 回答
0

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

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

    return validityPeriodQuery.getSingleResult();
}

这是视图调用的保存方法。如您所见,我只将当前实体传递给服务保存方法。在之前的Entity(currentValidityPeriod)中,我设置了另一个值。

@Override
public void save()
{       
    Date validFrom = new DateTime(DateTimeZone.forID("Europe/Vienna")).toDate();
    getEntity().setValidFrom(validFrom);

    currentValidityPeriod.setValidThru(validFrom);

    pointsValidityService.save(getEntity());

    addSavedSuccessfullyMessage();
}

这是将被调用的服务方法:

@Override
public void save(PointsValidityPeriod pointsValidityPeriod)
{
    super.save(pointsValidityPeriod);
}

...和超类的保存方法:

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

为什么实体管理器会持久化新实体并​​更新旧实体?我只是将一个实体传递实体管理器。尽管这是预期的行为,但我想知道为什么会这样。

于 2012-06-28T07:14:05.487 回答