java控制异常后全部回滚,java – JPA在异常/回滚情况下处理分离实体...

我有这个类,在持久性异常(在其他地方处理)的情况下,我采用三种方法来处理分离的实体状态:

@ManagedBean

@ViewScoped

public class EntityBean implements Serializable

{

@EJB

private PersistenceService service;

private Document entity;

public void update()

{

// HANDLING 1. ignore errors

service.transact(em ->

{

entity = em.merge(entity);

// some other code that modifies [entity] properties:

// entity.setCode(...);

// entity.setResposible(...);

// entity.setSecurityLevel(...);

}); // an exception may be thrown on method return (rollback),

// but [entity] has already been reassigned with a "dirty" one.

//------------------------------------------------------------------

// HANDLING 2. ensure entity is untouched before flush is ok

service.transact(em ->

{

Document managed = em.merge(entity);

// some other code that modifies [managed] properties:

// managed.setCode(...);

// managed.setResposible(...);

// managed.setSecurityLevel(...);

em.flush(); // an exception may be thrown here (rollback)

// forcing method exit without [entity] being reassigned.

entity = managed;

}); // an exception may be thrown on method return (rollback),

// but [entity] has already been reassigned with a "dirty" one.

//------------------------------------------------------------------

// HANDLING 3. ensure entity is untouched before whole transaction is ok

AtomicReference reference = new AtomicReference<>();

service.transact(em ->

{

Document managed = em.merge(entity);

// some other code that modifies [managed] properties:

// managed.setCode(...);

// managed.setResposible(...);

// managed.setSecurityLevel(...);

reference.set(managed);

}); // an exception may be thrown on method return (rollback),

// and [entity] is safe, it's not been reassigned yet.

entity = reference.get();

}

...

}

PersistenceService #transact(Consumer< EntityManager> consumer)可以抛出未经检查的异常.

目标是保持实体的状态与数据库的状态保持一致,即使在异常的情况下(防止实体在事务失败后变为“脏”).

>方法1.显然是天真的,并不保证连贯性.

>方法2.断言冲洗后没有任何问题.

>方法3.如果整个事务中存在异常,则阻止新实体分配

问题:

>方法3是否比方法2更安全?

>是否存在flush [excluded]和commit [included]之间抛出异常的情况?

>有没有一种标准的方法来处理这个常见问题?

谢谢

请注意,我已经能够回滚事务并关闭EntityManager(PersistenceService #transact会正常地执行它),但我需要解决数据库状态并且业务对象确实不同步.通常这不是问题.在我的情况下,这是问题,因为异常通常由BeanValidator生成(JPA方面,而不是JSF方面,依赖于用户输入的计算值),我希望用户输入正确的值并重试,而不会丢失他之前输入的价值观.

旁注:我正在使用Hibernate 5.2.1

这是PersistenceService(CMT)

@Stateless

@Local

public class PersistenceService implements Serializable

{

@PersistenceContext

private EntityManager em;

@TransactionAttribute(TransactionAttributeType.REQUIRED)

public void transact(Consumer consumer)

{

consumer.accept(em);

}

}

@DraganBozanovic

而已!第1点和第2点的重要解释.

我只是爱你在第3点详细说明一点,并给我一些关于实际用例的建议.

However, I would definitely not use AtomicReference or similar cumbersome constructs. Java EE, Spring and other frameworks and application containers support declaring transactional methods via annotations: Simply use the result returned from a transactional method.

当您必须修改单个实体时,事务方法只会将分离的实体作为参数并返回更新的实体,这很容易.

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)

>在大多数情况下,JSF控制器操作只调用EJB方法,从返回的容器中提取更新的实体并将它们重新分配给本地字段

>我的代码将被“一次性投手”逐渐污染,对我来说太多了.

可能我没有看到像我这样的大事,如果你能指出我正确的方向,我将非常感激.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值