多个PATCH请求REST端点

时间:2016-01-20 14:41:44

标签: angularjs spring-data-rest

我有一个Spring Data Rest项目,它暴露了由JPA和hibernate管理的实体。 我使用多个PATCH请求更新实体中的多个多对多关系。

所以我将PATCH请求发送到终点,实体网址列表作为每个多对多关系的主体。

补丁请求同时发生,因此一个请求继续进行,第二个并发请求给出

行已被其他交易更新或删除(或未保存的值映射不正确)

是否有同时PATCH实体的方法? 示例实体类似于

User {

List<Role> roles;  

List<Module> modules;

}

并发补丁请求发生在角色和模块上 修改:这是我用来修补的角度代码。

   var patchRequests = [];
   angular.forEach(copy, function (value, property) {
                    if (angular.isArray(copy[property])) {
                        // If array contains more than zero elements
                        if (copy[property].length > 0) {
                            patchRequests.push(
                                $http.patch(url,copy[property].join('\n'), {
                                    headers: {
                                        'Content-type': 'text/uri-list'
                                    }
                                }));
                        }
                    }
                });
    $q.all(patchRequests);

&#39;复制&#39;对象就像轰鸣声

{"roles":["http://localhost:9002/api/roles/1","http://localhost:9002/api/roles/3"],"modules":["http://localhost:9002/api/modules/1"],"subModules":[],"userName":"hrandika","password":"password","email":"h@local","activated":true}

编辑2: Spring Data rest只是一个接口

@Repository
public interface UserRepository extends PagingAndSortingRepository<User, Long>{

}

1 个答案:

答案 0 :(得分:1)

根据HTTP Patch规范:

  

服务器必须以原子方式永远应用整组更改   提供(例如,在此操作期间响应GET)a   部分修改的表示。如果是整个补丁文件   无法成功应用,那么服务器绝不能应用任何   变化。

单个补丁请求所做的所有更改都必须是原子的。这是通过使用容器或DB托管事务在Java中实现的。

因此,如果两个客户端向服务器发送补丁,则其中一个客户端必须等到第一个客户端完成其工作或者应该失败。

由于补丁可以更新任何字段(甚至是其他资源),因此两个单独的补丁请求可能会以不同方式更新同一字段(类似于DB竞争方案中使用的乐观锁示例)。除此之外,补丁指令通常应包含将状态1转换为状态2所需的步骤。使用JSONPatch f.e。一个请求可以从集合中删除字段,而另一个请求尝试将项目移动到另一个位置。由于这两个请求都依赖于他们目前所知的状态,盲目地应用这些值可能很危险。

HTTP Patch规范还提供了如何处理多个补丁请求的冲突场景的提示:

  

PATCH请求可以以幂等的方式发出,   这也有助于防止两者之间发生冲突造成的不良后果   PATCH在相似的时间范围内对同一资源进行请求。   来自多个PATCH请求的冲突可能比更危险   PUT冲突,因为一些补丁格式需要从a操作   已知的基点,否则它们会破坏资源。客户端   使用这种补丁应用程序应该使用条件请求   如果资源已更新,请求将失败   因为客户端上次访问了资源。例如,客户端   可以在PATCH上的If-Match标头中使用强大的ETag [RFC2616]   请求。

我建议遵循规范并使用ETag和If-Match HTTP标头来防止多个补丁请求发生冲突。