处理@RepositoryRestResource中的m-to-n关系 [英] Dealing with m-to-n relations in @RepositoryRestResource
问题描述
我想在一个调用中创建另一个资源的子资源。这些资源有 @ManyToMany
关系:用户和群组。
I want to create a sub-resource of another resource in one call. These resources have a @ManyToMany
relationship: Users and Groups.
我不想先创建一个用户,然后创建该组,然后在工作中显示该关系与Spring Data REST中的关系 - 仅仅因为我认为只有一个用户也与之相关联的资源本身不能存在,例如一个组。资源。为此,我需要一个单独的端点喜欢这个(这对我不起作用,否则我不会在这里)这会创建一个组,并在一个事务中设置关联的种子用户。
I do not want to create first a user, then the group and after that the relation as it is shown in Working with Relationships in Spring Data REST - simply because I think a resource that cannot exist on its own, such as a group, should only be created if at least one user is also associated with that resource. For this I require a single endpoint like this one (which is not working for me, otherwise I wouldn't be here) that creates a group and also sets the associated "seeding" user in one transaction.
目前,让这个为我工作的唯一方法是同步关系像这样手动:
Currently, the only way to make this work for me is to "synchronize" the relation manually like this:
public void setUsers(Set<AppUser> users) {
users.forEach(u -> u.getGroups().add(this));
this.users = users;
}
这将允许我
POST http://localhost:8080/groups
{
"name": "Group X",
"users": ["http://localhost:8080/users/1"]
}
<但是我的问题是,这对我来说感觉不对 - 它看起来似乎是一种解决方法而不是实际的Spring方式使这个要求起作用。那么..
but my problem with that is that this does not feel right to me - it does seem like a workaround and not the actual Spring-way to make this requirement work. So ..
我目前正在努力使用Spring的 @RepositoryRestResource创建关系资源
。我想创建一个新组并将其与调用用户关联,如下所示:
I'm currently struggling with creating relational resources using Spring's @RepositoryRestResource
. I want to create a new group and associate it with the calling user like this:
POST http://localhost:8080/users/1/groups
{
"name": "Group X"
}
但唯一的结果是响应 204 No Content
。我不知道为什么。这可能与我的另一个问题有关,也可能没有关系(参见这里)我尝试通过在JSON有效负载中设置相关资源来实现相同目的 - 这也不起作用。
but the only result is the response 204 No Content
. I have no idea why. This may or may not be related to another question of mine (see here) where I try to achieve the same by setting the relating resource in the JSON payload - that doesn't work either.
服务器端我收到以下错误:
Server side I am getting the following error:
tion$ResourceSupportHttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class org.springframework.hateoas.Resources<java.lang.Object>]]: java.lang.NullPointerException
如果您需要请告诉我任何具体的代码。
Please let me know in case you need any specific code.
我添加 exported = false
到 @RepositoryRestResource
of UserGroupRepository
:
@RepositoryRestResource(collectionResourceRel = "groups", path = "groups", exported = false)
public interface UserGroupRepository extends JpaRepository<UserGroup, Long> {
List<UserGroup> findByName(@Param("name") String name);
}
我发送邮件:
PATCH http://localhost:8080/users/1
{
"groups": [
{
"name": "Group X"
}
]
}
但是,结果仍然是服务器端的 204 No Content
和 ResourceNotFoundException
。
However, the result is still just 204 No Content
and a ResourceNotFoundException
on the server side.
基本上,以下单元测试应该是工作,但我也可以回答为什么这不起作用,这也说明了如何正确完成。
Essentially, the following unit test is supposed to work but I can also live with an answer why this cannot work and which also shows how this is done correctly.
@Autowired
private TestRestTemplate template;
private static String USERS_ENDPOINT = "http://localhost:8080/users/";
private static String GROUPS_ENDPOINT = "http://localhost:8080/groups/";
// ..
@Test
@DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD)
public void whenCreateUserGroup() {
// Creates a user
whenCreateAppUser();
ResponseEntity<AppUser> appUserResponse = template.getForEntity(USERS_ENDPOINT + "1/", AppUser.class);
AppUser appUser = appUserResponse.getBody();
UserGroup userGroup = new UserGroup();
userGroup.setName("Test Group");
userGroup.setUsers(Collections.singleton(appUser));
template.postForEntity(GROUPS_ENDPOINT, userGroup, UserGroup.class);
ResponseEntity<UserGroup> userGroupResponse = template.getForEntity(GROUPS_ENDPOINT + "2/", UserGroup.class);
Predicate<String> username = other -> appUser.getUsername().equals(other);
assertNotNull("Response must not be null.", userGroupResponse.getBody());
assertTrue("User was not associated with the group he created.",
userGroupResponse.getBody().getUsers().stream()
.map(AppUser::getUsername).anyMatch(username));
}
然而,行
userGroup.setUsers(Collections.singleton(appUser));
将破坏此测试并返回 404 Bad Request
。
推荐答案
根据 SDR参考:
POST
POST
仅支持集合关联。向集合添加新元素。支持的媒体类型:
Only supported for collection associations. Adds a new element to the collection. Supported media types:
text / uri-list
- 指向要添加到关联的资源的URI。
text/uri-list
- URIs pointing to the resource to add to the association.
所以要将 group
添加到 user
尝试这样做:
So to add group
to user
try to do this:
POST http://localhost:8080/users/1/groups (with Content-Type:text/uri-list)
http://localhost:8080/groups/1
其他信息。
这篇关于处理@RepositoryRestResource中的m-to-n关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!