我正在使用JAX-RS提供基于HTTP的接口来管理数据模型。数据模型存储在数据库中,并通过JPA进行交互。如何使用JAX-RS,Spring和JPA管理事务
这让我修改界面,数据模型,以适应REST客户端,大多似乎运作得非常好。但是,我不确定如何处理由JAX-RS资源提供的方法需要事务的场景,这会影响JPA获取,更新,提交on-tx-end模式,因为只有事务包装get操作,所以更新从不提交。如果单个REST操作需要多个JPA操作,我可以看到发生同样的问题。
由于我使用Spring的事务支持,很明显的事情是应用@Transactional
在JAX-RS资源,这些方法。然而,为了实现这个目标,Spring需要管理JAX-RS资源的生命周期,我知道的用例中有资源是在需要时通过`new'创建的,这使我有点紧张。
我能想到以下解决方案:
- 更新我的JPA的方法来提供我想要的一切,从我的REST接口做原子的交易管理版本。应该工作,将事务保留在JAX-RS层之外,但是阻止获取,更新,提交on-tx-end模式,并且意味着我需要创建非常精细的JPA接口。
- 注入资源对象;但它们通常是有状态的,至少保存着正在与之交互的对象的ID
- 放弃资源的层次结构,并在管理根的整个层次结构的根处注入大而无状态的超级资源;没有凝聚力,大的服务
- 有一个注入的,无状态的,支持事务的帮助对象的层次结构,它能“隐藏”实际的资源;资源被实例化并保存状态,但委托方法调用到帮助对象
任何人有任何建议吗?我很可能错过了某个关键点。
更新 - 解决了周围没有获取,更新交易的,提交-ON-TX-密切流动,我可以公开了EntityManager合并(对象)的方法和手动调用它。不够整齐,但并没有解决更大的问题。
更新2 @skaffman 代码示例: 在JPA服务层,注入,注释工作
public class MyEntityJPAService {
...
@Transactional(readOnly=true) // do in transaction
public MyEntity getMyEntity(final String id) {
return em.find(MyEntity.class, id);
}
在JAX-RS资源,通过新的,没有交易产生
public class MyEntityResource {
...
private MyEntityJPAService jpa;
...
@Transactional // not injected so not effective
public void updateMyEntity(final String id, final MyEntityRepresentation rep) {
MyEntity entity = jpa.getMyEntity(id);
MyEntity.setSomeField(rep.getSomeField());
// no transaction commit, change not saved...
}
这些建议是按照首选顺序排列的吗? – brainOverflow 2013-04-19 17:19:08