问题描述
我正在尝试做一个简单的Spring应用程序。它需要公开REST端点并将其保存到关系数据库中。
我带着您的示例项目。我能够完成所有操作(POST,PATCH,PUT,GET),正如您在指南中提到的那样。
然而,我尝试创建添加关系到Person Entity类和事物开始分崩离析。
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
私人长ID;
private String firstName;
private String lastName;
@OneToOne(cascade = {CascadeType.ALL})
private PersonDetails personDetails;
@OneToOne(cascade = {CascadeType.ALL})
私人PersonChildren personChildren;
/// Getter和setter除了id之外的所有内容。
@Entity
public class PersonChildren {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
私人长ID;
private String childFirstName;
private String childLastName;
@OneToOne(mappedBy =personChildren,可选= false)
私人Person person;
/// Getter和setter除了id之外的所有内容。
@Entity
public class PersonDetails {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
私人长ID;
私人字符串电子邮件;
私人字符串phoneNumber;
@OneToOne(mappedBy =personDetails,可选= false)
私人Person person;
/// Getter和setter除了id之外的所有内容。
$ b @RepositoryRestResource(collectionResourceRel =people,path =people)
public interface PersonRepository extends PagingAndSortingRepository< Person,Long> {
列表< Person> findByLastName(@Param(name)字符串名称);
$ b
build.gradle
buildscript {
repositories {
maven {urlhttp:// repo。 spring.io/libs-release}
mavenLocal()
mavenCentral()
}
依赖项{
classpath(org.springframework.boot:spring-boot -gradle-plugin:1.1.1.RELEASE)
}
}
apply plugin:'java'
apply plugin:'eclipse'
应用插件:'idea'
apply插件:'spring-boot'
jar {
baseName ='gs-accessible-data-rest'
version =' 0.1.0'
}
知识库{
mavenLocal()
mavenCentral()
maven {urlhttp://repo.spring.io / libs-release}
}
依赖关系{
compile(org.springframework.boot:spring-boot-starter-web)
compile( org.springframework.boot:spring-boot-starter-data-jpa)
compile(com.h2database:h2)
compi le(org.springframework.data:spring-data-rest-webmvc)
}
任务包装(类型:包装器){
gradleVersion ='1.11'
通话:
$ curl -i -X POST -HContent-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< / code>
响应:
HTTP / 1.1 201创建
服务器:Apache-Coyote / 1.1
< code>
位置:http:// localhost:8080 / people / 1
< / code>
Content-Length:0
日期:2014年6月26日星期四05:42:45 GMT
$ curl http:// localhost:8080 / people
{
timestamp:1403761371011,
status:500,
error:内部服务器错误,
exception:org.springframework .http.converter.HttpMessageNotWritableException,
message:无法写入JSON:检测到具有相同关系类型的多个关联链接!消除关联@ javax.persistence.OneToOne(可选= false,targetEntity = void,cascade = [],fetch = EAGER,orphanRemoval = false,mappedBy = personChildren)private com.ds.dao.rest.Person com.ds.dao.rest.PersonChildren.person using @RestResource!(通过引用链:org.springframework.hateoas .PagedResources [\_embedded \] - > java.util.UnmodifiableMap [\people \] - > java.util.ArrayList [0]);嵌套的异常是com.fasterxml.jackson。 databind.JsonMappingException:检测到具有相同关系类型的多个关联链接!Disambiguate associati on @ javax.persistence.OneToOne(可选= false,targetEntity = void,cascade = [],fetch = EAGER,orphanRemoval = false,mappedBy = personChildren)private com.ds.dao.rest.Person com.ds.dao.rest .PersonChildren.person使用@RestResource! (通过参考链: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作为依赖关系,否则无法识别。
这与未回答的问题
更新:
它只与e OneToOne
映射到 Person
类中。如果我在 Person
中添加了两个类, personDetails
和 personChildren
与 OneToOne
映射。它不工作。
我也尝试添加 @JointColumn(name =person_details)
和 @JointColumn(name =person_children)
至 personDetails
和 personChildren
。它也没有工作。
原因很简单:关联实体的关系名是从属性派生的包含类的名称。因此 PersonDetails
和 PersonChildren
都希望创建出站链接到 Person
名为 person
。如果我们提出这个问题,它会看起来像这样
{_links:{
person:{href:...} ,< - 来自PersonDetails
person:{href:...}< - 来自PersonChildren的
}
的一个
这当然是无效的。此外,排列数组中的两个链接不会让您区分两个链接(哪一个来自 PersonDetails
,哪一个来自 PersonChildren
。
所以这里有几个选项:
- 手动命名这些类型的关系。您可以使用
@RestResource注释
并将注释的Person
rel
属性配置为不同于person
的内容。 - 您希望两者中的任何一个都不能被导出。可以使用完全相同的注释来防止链接被渲染,只需设置<$ c $在
@RestResource
到false
中导出标志,链接将不会呈现。如果来自PersonDetails
的指针在代码中恰好相关,但实际上不是JSON表示,则这可能很有用。
I am trying to doing a simple Spring app. It needs to expose REST endpoints and save it to a relational database.
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.
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'
}
Call:
$ 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"
}
Question 1: I am able to do a post but my GET keeps failing.
Question 2: Why am I getting this error when Post succeeds?
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?
Question 4: Is @RepositoryRestResource the problem? It is not recognized unless I add spring-data-rest-webmvc as dependency.
This is similar to the unanswered questionSpring Data Rest Ambiguous Association Exception
Update:
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.
I also tried adding @JointColumn(name="person_details")
and @JointColumn(name="person_children")
to personDetails
and personChildren
. It did NOT work either.
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
}
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
.
So there are a few options here:
- Manually name the relations of those types. You can annotate the
Person
properties with@RestResource
and configure therel
attribute of the annotation to something different thanperson
. - 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
tofalse
and the link will not be rendered. This might be useful if the pointer e.g. fromPersonDetails
is just relevant within the code, but actually not in a JSON representation.
这篇关于Spring Data REST - 检测到具有相同关系类型的多个关联链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!