首先,这个解决方案对我来说是没有选择的,因为我无法更改持久性单元。
我的问题是我使用 JTA 实体管理器,但我只需要一个用例,例如事务:
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);
}
您会看到,有一个保存调用,但如果更新出错,则必须回滚此保存,那么我该如何实现呢?有什么想法吗?
这完全取决于您的方法事务注释。如果没有,则默认情况下,事务边界将设置为业务方法,如 JB 所指出的那样。
因此,整个方法是一笔交易。通常,save
方法的事务管理很重要(如果是REQUIRED
或REQUIRES_NEW
是有区别的),但在这种情况下,您进行的是本地方法调用 - 而不是业务方法调用,因此save
方法的任何事务管理设置都不适用于此处。
因此,如果update
失败,您可以基于自动事务回滚(如果是生成回滚 Tx 的异常的 EntityManager 调用),也可以手动注入SessionContext
并在其上调用setRollbackOnly()
,字里行间的内容:
@Resource
SessionContext ctx;
public boolean saveWithResult(PointsValidityPeriod pointsValidityPeriod)
{
// ...
if (updatePrevious(pointsValidityPeriod.getValidFrom()) != 1)
{
// ...
ctx.setRollbackOnly();
// ...
}
}
我有解决方案,但我不知道为什么会这样。也许有人可以向我解释一下。在我的支持豆中,有保存方法。有 2 个实体。getEntity() 是支持bean使用的当前实体,currentValidityPeriod 是该实体的另一个实例,它保存实体的最新数据库状态,由 currentValidityPeriod = pointsValidityService.findCurrent();findCurrent() 只是一个执行 TypedQuery 的方法:
public PointsValidityPeriod findCurrent()
{
TypedQuery<PointsValidityPeriod> validityPeriodQuery = entityManager.createNamedQuery(PointsValidityPeriod.FindCurrent, PointsValidityPeriod.class);
return validityPeriodQuery.getSingleResult();
}
这是视图调用的 save 方法。如您所见,我只将当前实体传递给服务保存方法。在上一个实体(当前有效期)中,我设置了另一个值。
@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);
}
为什么实体管理器保留新实体并更新旧实体?我只是将一个实体传递给实体管理器。虽然这是预期的行为,但我想知道为什么会这样。