Java JPA在异常/回滚情况下处理分离实体状态的正确方法
我有这个类,我想到了三种在持久性异常(在别处处理)的情况下处理分离实体状态的方法:Java JPA在异常/回滚情况下处理分离实体状态的正确方法,java,hibernate,jpa,ejb,jpa-2.1,Java,Hibernate,Jpa,Ejb,Jpa 2.1,我有这个类,我想到了三种在持久性异常(在别处处理)的情况下处理分离实体状态的方法: @德拉甘博扎诺维奇 就这样!对第一点有很好的解释。二, 我希望你能对第三点做进一步的阐述。并给我一些关于真实世界用例的建议 然而,我绝对不会使用原子引用或类似的繁琐构造。JavaEE、Spring和其他框架和应用程序容器支持通过注释声明事务性方法:只需使用从事务性方法返回的结果 当您必须修改单个实体时,事务性方法只需将分离的实体作为参数并返回更新的实体,这很容易 public Document updateDo
@德拉甘博扎诺维奇 就这样!对第一点有很好的解释。二, 我希望你能对第三点做进一步的阐述。并给我一些关于真实世界用例的建议 然而,我绝对不会使用原子引用或类似的繁琐构造。JavaEE、Spring和其他框架和应用程序容器支持通过注释声明事务性方法:只需使用从事务性方法返回的结果 当您必须修改单个实体时,事务性方法只需将分离的实体作为参数并返回更新的实体,这很容易
public Document updateDocument(Document doc)
{
Document managed = em.merge(doc);
// managed.setXxx(...);
// managed.setYyy(...);
return managed;
}
但当您需要在单个事务中修改多个时,该方法可能会成为一个真正的难题:
public LinkTicketResult linkTicket(Node node, Ticket ticket)
{
LinkTicketResult result = new LinkTicketResult();
Node managedNode = em.merge(node);
result.setNode(managedNode);
// modify managedNode
Ticket managedTicket = em.merge(ticket);
result.setTicket(managedTicket);
// modify managedTicket
Remark managedRemark = createRemark(...);
result.setRemark(managedemark);
return result;
}
在这种情况下,我的痛苦:
@EJB
)LinkTicketResult
LinkTicketParameters
)可能我没有看到眼前的大问题,如果您能为我指出正确的方向,我将非常感激。不确定这是否完全正确,但只有一种方法可以在异常后恢复:回滚并关闭EM。从 实体管理器引发的异常意味着您必须回滚 启动数据库事务并立即关闭EntityManager (稍后将详细讨论)。如果您的EntityManager绑定到 应用程序,您必须停止应用程序。回退 数据库事务不会将业务对象放回 说明他们在交易开始时。这意味着 数据库状态和业务对象确实不同步。通常 这不是问题,因为异常是不可恢复的,并且 无论如何,回滚后必须重新开始工作单元 --编辑-- 也看到 附言:否决票不是我的
AtomicReference
或类似的繁琐构造。JavaEE、Spring和其他框架和应用程序容器支持通过注释声明事务性方法:只需使用从事务性方法返回的结果@downvoter您能解释一下吗?我没有投反对票,但我可以想象这是因为不可编译的代码。@tak3shi这是一个改编为示例的代码片段,如果有人因为这个原因投了反对票,我很抱歉他思维有限;)我不明白整件事。。。。是否管理EM用户或容器?它的范围是什么?应用程序?@Gab em是CMT。控制器是一个JSF
@ViewScoped
@ManagedBean
。请参阅更新的问题。谢谢,但这不是重点;我已经能够回滚事务并关闭EntityManager(PersistenceService#transact
可以很好地完成),但我需要解决数据库状态和业务对象不同步的问题。通常这不是问题。在我的例子中,这就是问题所在,因为异常通常是由BeanValidator
生成的,我希望用户输入正确的值并重试,而不会丢失他以前输入的值。@MicheleMariotti我看不出有任何理由在BeanValidator异常后丢失这些值。您的问题没有说明问题。@tak3shi我更新了问题,以便更好地解释代码中导致问题的原因。将“脏”实体分配给[entity]字段时,我将丢失该值,因为“脏”实体不再可合并(即具有递增的@Version
值)。谢谢!“我对第三点做了一些阐述,如果你能在现实世界的案例中给出一些实用的建议,我将不胜感激。”MicheleMariotti说,这已经有点基于观点了。我认为单独提出一项质询较为合适。我想说,对于方法结果,一个单独的shotter类仍然比一个散乱的shotterAtomicReference
s更具可读性
public Document updateDocument(Document doc)
{
Document managed = em.merge(doc);
// managed.setXxx(...);
// managed.setYyy(...);
return managed;
}
public LinkTicketResult linkTicket(Node node, Ticket ticket)
{
LinkTicketResult result = new LinkTicketResult();
Node managedNode = em.merge(node);
result.setNode(managedNode);
// modify managedNode
Ticket managedTicket = em.merge(ticket);
result.setTicket(managedTicket);
// modify managedTicket
Remark managedRemark = createRemark(...);
result.setRemark(managedemark);
return result;
}