Spring Data REST - 检测到多个具有相同关系类型的关联链接 [英] Spring Data REST - Detected multiple association links with same relation type

查看:22
本文介绍了Spring Data REST - 检测到多个具有相同关系类型的关联链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试做一个简单的 Spring 应用程序.它需要公开 REST 端点并将其保存到关系数据库中.

I am trying to doing a simple Spring app. It needs to expose REST endpoints and save it to a relational database.

我拿了你的示例项目,http://spring.io/guides/gs/accessing-data-rest/.我能够执行您指南中提到的所有操作(POST、PATCH、PUT、GET).

I took your sample project, http://spring.io/guides/gs/accessing-data-rest/. I am able to do all the operations( POST, PATCH, PUT, GET) as mentioned in your guide.

但是,我尝试为 Person Entity 类创建添加关系,但事情开始分崩离析.

However I tried creating adding relationships to Person Entity class and things start to fall apart.

@Entity
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String firstName;
    private String lastName;

    @OneToOne(cascade = {CascadeType.ALL})
    private PersonDetails personDetails;

    @OneToOne(cascade = {CascadeType.ALL})
    private PersonChildren personChildren;

     ///Getter and setters for everything except id.
}


@Entity
public class PersonChildren {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String childFirstName;
    private String childLastName;

    @OneToOne(mappedBy="personChildren", optional=false)
    private Person person;

///Getter and setters for everything except id.
}


@Entity
public class PersonDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String email;
    private String phoneNumber;

    @OneToOne(mappedBy="personDetails",optional=false)
    private Person person;

///Getter and setters for everything except id.
}


@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {

    List<Person> findByLastName(@Param("name") String name);

}

build.gradle

buildscript {
    repositories {
        maven { url "http://repo.spring.io/libs-release" }
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.1.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'gs-accessing-data-rest'
    version = '0.1.0'
}

repositories {
    mavenLocal()
    mavenCentral()
    maven { url "http://repo.spring.io/libs-release" }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("com.h2database:h2")
    compile("org.springframework.data:spring-data-rest-webmvc")
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.11'
}

调用:

$ curl -i -X POST -H "Content-Type:application/json" -d '{ "firstName":"John", "lastName": "Doe", "personDetails": { "email": "john@gmail.com", "phoneNumber": "001-002-0003" }, "personChildren": {"childFirstName": "Mary", "childLastName": "Martin" } }' <code> http://localhost:8080/people </code>

Response: 
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
<code>
Location: http://localhost:8080/people/1
</code>
Content-Length: 0
Date: Thu, 26 Jun 2014 05:42:45 GMT

$ curl  http://localhost:8080/people

{
  "timestamp" : 1403761371011,
  "status" : 500,
  "error" : "Internal Server Error",
  "exception" : "org.springframework.http.converter.HttpMessageNotWritableException",
  "message" : "Could not write JSON: Detected multiple association links with same relation type! Disambiguate association @javax.persistence.OneToOne(optional=false, targetEntity=void, cascade=[], fetch=EAGER, orphanRemoval=false, mappedBy=personChildren) private com.ds.dao.rest.Person com.ds.dao.rest.PersonChildren.person using @RestResource! (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.UnmodifiableMap["people"]->java.util.ArrayList[0]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Detected multiple association links with same relation type! Disambiguate association @javax.persistence.OneToOne(optional=false, targetEntity=void, cascade=[], fetch=EAGER, orphanRemoval=false, mappedBy=personChildren) private com.ds.dao.rest.Person com.ds.dao.rest.PersonChildren.person using @RestResource! (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.UnmodifiableMap["people"]->java.util.ArrayList[0])",
  "path" : "/people"
}

问题 1:我可以发帖,但我的 GET 一直失败.

Question 1: I am able to do a post but my GET keeps failing.

问题 2:为什么当 Post 成功时我会收到这个错误?

Question 2: Why am I getting this error when Post succeeds?

问题 3:有没有好的 Spring 指南可以帮助 REST 和 JPA?如果您仍在研究这些模块,我可以查看哪些示例?

Question 3: Is there a good Spring Guide that will help with REST and JPA? If you are still working on these modules what examples can I look at?

问题 4:@RepositoryRestResource 是问题吗?除非我将 spring-data-rest-webmvc 添加为依赖项,否则无法识别它.

Question 4: Is @RepositoryRestResource the problem? It is not recognized unless I add spring-data-rest-webmvc as dependency.

这类似于未回答的问题Spring Data Rest 模糊关联异常

更新:

它仅使用 Person 类中的一个 OneToOne 映射.如果我在 PersonOneToOne 映射中添加两个类,personDetailspersonChildren.它不起作用.

It is working with only one OneToOne mapping in Person class. If I add both classes, personDetails and personChildren in Person with OneToOne mapping. It is NOT working.

我还尝试将 @JointColumn(name="person_details")@JointColumn(name="person_children") 添加到 personDetailspersonChildren.它也不起作用.

I also tried adding @JointColumn(name="person_details") and @JointColumn(name="person_children") to personDetails and personChildren. It did NOT work either.

推荐答案

原因很简单:关联实体的关系名称派生自包含类的属性名称.所以PersonDetailsPersonChildren 都想创建一个到名为personPerson 的出站链接.如果我们渲染它,它看起来像这样

The reason for that is pretty simple: the relation names for associated entities are derived from the property names of the containing class. So both PersonDetails and PersonChildren want to create an outbound link to a Person named person. If we rendered that, it would look something like this

{ _links : { 
   person : { href : … }, <- the one from PersonDetails
   person : { href : … }  <- the one from PersonChildren
}

这当然是无效的.此外,将两个链接排列在一个数组中将不再允许您区分这两个链接(哪个来自 PersonDetails,哪个来自 PersonChildren.

This is of course invalid. Also, lining up the two links in an array would not allow you to distinguish between the two links anymore (which one is coming from PersonDetails and which one is coming from PersonChildren.

这里有几个选项:

  1. 手动命名这些类型的关系.您可以使用 @RestResource 注释 Person 属性并将注释的 rel 属性配置为与 person 不同的内容.
  2. 您希望两者中的任何一个都不导出.可以使用完全相同的注释来防止链接被渲染.只需将 @RestResource 中的 exported 标志设置为 false,链接将不会被呈现.如果指针例如from PersonDetails 仅在代码中相关,但实际上不在 JSON 表示中.
  1. Manually name the relations of those types. You can annotate the Person properties with @RestResource and configure the rel attribute of the annotation to something different than person.
  2. You want any of the two not exported at all. The very same annotation can be used to prevent the link from being rendered at all. Simply set the exported flag in @RestResource to false and the link will not be rendered. This might be useful if the pointer e.g. from PersonDetails is just relevant within the code, but actually not in a JSON representation.

这篇关于Spring Data REST - 检测到多个具有相同关系类型的关联链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆