Spring Data REST – 检测到具有相同关系类型的多个关联链接

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

我带了你的示例项目, http://spring.io/guides/gs/accessing-data-rest/ 。 我可以按照指南中的说明进行所有操作(POST,PATCH,PUT,GET)。

但是我尝试创建添加到Person Entity类的关系,事情开始崩溃。

@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 { List 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" } }'  http://localhost:8080/people  Response: HTTP/1.1 201 Created Server: Apache-Coyote/1.1  Location: http://localhost:8080/people/1  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一直都失败了。

问题2:发布成功后,为什么会出现此错误?

问题3:是否有一个好的Spring指南可以帮助REST和JPA? 如果您仍在使用这些模块,我可以查看哪些示例?

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

这类似于未解决的问题Spring Data Rest Ambiguous Association Exception

更新

它只在Person类中使用一个OneToOne映射。 如果我在Person添加两个类, personDetailspersonChildren ,并使用OneToOne映射。 它不起作用。

我还尝试将@JointColumn(name="person_details")@JointColumn(name="person_children")personDetailspersonChildren 。 它也没用。

原因很简单:关联实体的关系名称是从包含类的属性名称派生的。 所以PersonDetailsPersonChildren希望创建一个名为person的出站链接。 如果我们渲染它,它看起来就像这样

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

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

所以这里有几个选项:

  1. 手动命名这些类型的关系 。 您可以使用@RestResource注释Person属性,并将注释的rel属性配置为与@RestResource不同的值。
  2. 您希望两者中的任何一个都不会导出 。 可以使用完全相同的注释来防止链接被渲染。 只需将@RestResourceexported标志设置为false ,就不会呈现链接。 如果例如来自PersonDetails的指针在代码中是相关的,但实际上不在JSON表示中,则这可能是有用的。