Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用JAX-RS、Spring和JPA管理事务_Spring_Jpa_Transactions_Jax Rs - Fatal编程技术网

如何使用JAX-RS、Spring和JPA管理事务

如何使用JAX-RS、Spring和JPA管理事务,spring,jpa,transactions,jax-rs,Spring,Jpa,Transactions,Jax Rs,我正在使用JAX-RS提供一个基于HTTP的接口来管理数据模型。数据模型存储在数据库中,并通过JPA与之交互 这使我能够修改数据模型的接口以适应REST客户机,而且大多数情况下似乎工作得很好。但是,我不确定如何处理JAX-RS资源提供的方法需要事务的场景,这会影响JPA get、update、commit on tx end模式,因为只有一个事务包装get操作,所以永远不会提交更新。如果单个REST操作需要多个JPA操作,我可以看到同样的问题 当我使用Spring的事务支持时,显然要做的事情是将

我正在使用JAX-RS提供一个基于HTTP的接口来管理数据模型。数据模型存储在数据库中,并通过JPA与之交互

这使我能够修改数据模型的接口以适应REST客户机,而且大多数情况下似乎工作得很好。但是,我不确定如何处理JAX-RS资源提供的方法需要事务的场景,这会影响JPA get、update、commit on tx end模式,因为只有一个事务包装get操作,所以永远不会提交更新。如果单个REST操作需要多个JPA操作,我可以看到同样的问题

当我使用Spring的事务支持时,显然要做的事情是将
@Transactional
应用于JAX-RS资源中的这些方法。然而,为了让这项工作正常进行,Spring需要管理JAX-RS资源的生命周期,我所知道的使用示例在需要时通过“new”创建资源,这让我有点紧张

我可以想出以下解决办法:

  • 更新我的JPA方法,以提供我想从REST接口原子地执行的所有操作的事务管理版本。应该可以工作,将事务排除在JAX-RS层之外,但阻止了get、update、commit on tx end模式,这意味着我需要创建一个非常精细的JPA接口
  • 注入资源对象;但它们通常是有状态的,至少包含与之交互的对象的ID
  • 抛弃资源的层次结构,在根目录下注入大的、无状态的超级资源,从该根目录管理整个层次结构;没有凝聚力,大服务
  • 具有注入的、无状态的、支持事务的助手对象的层次结构,这些对象“隐藏”实际资源;资源被实例化并保持状态,但将方法调用委托给助手对象
  • 有人有什么建议吗?我很可能在什么地方遗漏了一些关键点


    更新-为了解决在get、Update、commit on tx close流中缺少事务的问题,我可以公开EntityManager合并(object)方法并手动调用它。不整洁,但不能解决更大的问题


    更新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资源中,由new创建,没有事务

    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...
    }
    

    我有一些建议

  • 在JPA和JAX-RS层之间引入一个层。该层将由Spring管理的
    @Transactional
    bean组成,并将从组件JPA调用组成各种业务级别的操作。这有点类似于(1),但保持了JPA层的简单性

  • 用Spring MVC替换JAX-RS,后者提供相同(或类似)的功能,包括
    @PathVariable
    @ResponseBody

  • 使用
    TransactionProxyFactorybean
    以编程方式将JAX-RS对象包装到事务代理中。这将检测您的
    @Transactional
    注释,并生成一个代理来尊重它们

  • 使用
    @Configurable
    和AspectJ LTW允许Spring尊重
    @Transactional
    ,即使您使用“new”创建对象也是如此。看


  • 这些建议是否按优先顺序排列(根据您)?