【问题标题】:Deleting an association over REST in Spring Data REST+HATEOAS在 Spring Data REST+HATEOAS 中删除基于 REST 的关联
【发布时间】:2015-04-26 23:59:07
【问题描述】:

我想知道如何通过 REST 调用删除多对多关联。我能够创建记录并关联它们,但不知道如何删除。

我有一个 Spring Boot 项目,我在其中使用 REST 和 HATEOAS 来绕过服务和控制器并直接公开我的存储库。

我有一个用户模型/域类

@Entity
@Table(name = "usr")
public class User implements Serializable {

private static final long serialVersionUID = 1L;

@Version
private long version = 0;

@Id
@GeneratedValue(generator="optimized-sequence")
private Long id;

@Column(nullable = false, unique = true, length = 500)
@Size(max = 500)
private String userName;

@Column(nullable = false, length = 500)
@Size(max = 500)
private String firstName;

@Column(nullable = false, length = 500)
@Size(max = 500)
private String lastName;

@ManyToMany(    fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable( name="user_role",
            joinColumns={ @JoinColumn(  name = "user_id", 
                                        nullable = false
                                    ) 
                        }, 
            inverseJoinColumns={ @JoinColumn(   name="role_id", 
                                                nullable=false
                                            ) 
                                }
)
private Set<Role> roles = new HashSet<Role>(0);

...Getters/Setters Below...

如您所见,我有一个 roles 成员,它与 Role 类是多对多关联,其代码如下:

@Entity
public class Role {

@Id
@GeneratedValue(generator="optimized-sequence")
private Long id;

@Column(nullable = false)
private String name;

@Column(nullable = false)
private String description;

...Getters/Setters Below...

我的存储库如下所示:

用户存储库

public interface UserRepository extends 
        JpaRepository<User, Long>, JpaSpecificationExecutor<User> {

    List<User> findByUserName(String username);

}

角色存储库

public interface RoleRepository 
        extends JpaRepository<Role, Long> {

}

现在,一切都很好。当我从浏览器访问项目根目录时,我得到 JSON+HAL 格式的存储库索引/目录。太棒了。

(请注意,我从下面的测试中删除了 http:// 部分,因为 StackOverflow 将其计入我的链接配额)

我,使用 WizTools REST 客户端,HTTP.POST 到角色 (localhost:8080/resttest/roles) 存储库并创建一个新角色。成功,创建角色 ID #4。

然后我 POST 到用户存储库以创建一个用户 (localhost:8080/resttest/users)。成功,创建了用户 ID #7。

然后我 PUT 到用户存储库以创建与角色的关联:

PUT localhost:8080/resttest/users/7/roles
Content-type: uri-list
Body: localhost:8080/resttest/roles/4

太棒了!协会提出。用户 9 现在与角色 4 相关联。

现在我无法弄清楚如何删除这个关联。

我使用与上述相同的命令发送 HTTP DELETE 而不是 PUT。

DELETE localhost:8080/resttest/users/7/roles
Content-type: uri-list
Body: localhost:8080/resttest/roles/4

我回来了:HTTP/1.1 405 Method Not Allowed

{
    "timestamp":1424827169981,
    "status":405,
    "error":"Method Not  Allowed",
    "exception": "org.springframework.web.HttpRequestMethodNotSupportedException",
    "message":"Request method 'POST' not supported"
}

【问题讨论】:

  • 请问有什么解决办法!?

标签: spring rest spring-data-rest spring-hateoas


【解决方案1】:

尽管使用剩余元素创建PUT 请求可以解决问题,但DELETE 是一个公认的删除关联资源的命令,并且在大多数情况下更易于使用。

至于你的例子,这应该有效:

DELETE localhost:8080/resttest/users/7/roles/4

另外,在创建关联时,负载中应该有 URI。您不需要将整个 URL 写在正文中,这就足够了:

PUT localhost:8080/resttest/users/7/roles
Content-type: uri-list
Body: /roles/4

希望这会有所帮助。

【讨论】:

  • 这很不方便,因为所有其他请求(put、post、get)都依赖于链接而不是 ID。要执行删除代码,需要编写从对象_link中提取id。
【解决方案2】:

来自文档:

删除

...

405 Method Not Allowed - 如果关联是非可选的

PUT 表示你替换整个roles 集合。所以要删除一个链接,你PUT所有剩余的链接。如果您只有一个链接并且想要删除它,您将 PUT 一个空集合:

PUT localhost:8080/resttest/users/7/roles
Content-type: uri-list
Body:

顺便说一句:您不会发送带有DELETE 请求的正文。这没有意义。

编辑

另请参阅 Spring HATEOAS 开发人员的 this answer。

【讨论】:

  • 感谢您的回复。这解释了很多。我有两个后续问题。在关联可能很多的情况下,有没有办法只删除一个而不是放一整套而不需要不再需要的?我的另一个问题是,什么是非可选关联?
  • 我不能再编辑评论了。只是想澄清一下。并不是说 DELETE one 必须是一个 DELETE http 方法,它可以是任何方法,只要它有助于删除一个关联而不是整个集合而不需要一个您需要的关联。还是我必须为那个桥接表创建一个存储库?
  • @BKaun 您可以使用POST 添加单个 URI,但是没有方便的方法来删除单个 URI。非可选意味着必须有一个值。通常情况下,列不是nullable。我猜一个集合在语义上总是非可选的:它可能是空的,但它总是在那里。
  • 非常感谢,zeroflagL。在发帖之前,我到处搜索,你给的链接我也看到了。当然,由于该线程中没有“答案”,我在阅读了 cmets 并没有发现任何关于删除的内容后放弃了(瞥了一眼他的 cmets,我注意到他在谈论 PATCH/PUT 而我正在追逐 DELETE,所以我把它关闭了挫折)。几乎每个 curl 示例都显示了普通的添加和删除,就关联而言,它们只显示添加。我变得非常沮丧,以至于我不得不在这里发帖。你帮了大忙。
猜你喜欢
  • 2014-03-07
  • 2013-10-31
  • 2014-08-16
  • 2015-03-03
  • 2016-05-23
  • 2014-07-05
  • 1970-01-01
  • 2018-07-23
  • 2015-12-07
相关资源
最近更新 更多