Spring Data Rest: Detected multiple association links with same relation type
Regarding this question, I checked out Spring Data Rest Ambiguous Association Exception but couldn't get it to work for me.
As you can see in my code below, I added @RestResource
annotation with rel
equal to some other value.
Similar to the question above, POST requests work, but GET requests throw exception about multiple association links with the same relation type:
"Could not write JSON: Detected multiple association links with same relation type! Disambiguate association @org.springframework.data.rest.core.annotation.RestResource(rel=createdBy, exported=true, path=, description=@org.springframework.data.rest.core.annotation.Description(value=)) @javax.persistence.ManyToOne(optional=true, targetEntity=void, cascade=[], fetch=EAGER) @javax.persistence.JoinColumn(referencedColumnName=ASSIGNABLE_ID, nullable=false, unique=false, name=CREATED_BY, updatable=true, columnDefinition=, foreignKey=@javax.persistence.ForeignKey(name=, value=CONSTRAINT, foreignKeyDefinition=), table=, insertable=true) private com.ag.persistence.domain.PersonEntity com.ag.persistence.domain.TeamEntity.createdBy using @RestResource! (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.UnmodifiableMap["persons"]->java.util.ArrayList[0]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Detected multiple associa tion links with same relation type! Disambiguate association @org.springframework.data.rest.core.annotation.RestResource(rel=createdBy, exported=true, path=, description=@org.springframework.data.rest.core.annotation.Description(value=)) @javax.persistence.ManyToOne(optional=true, targetEntity=void, cascade=[], fetch=EAGER) @javax.persistence.JoinColumn(referencedColumnName=ASSIGNABLE_ID, nullable=false, unique=false, name=CREATED_BY, updatable=true, columnDefinition=, foreignKey=@javax.persistence.ForeignKey(name=, value=CONSTRAINT, foreignKeyDefinition=), table=, insertable=true) private com.ag.persistence.domain.PersonEntity com.ag.persistence.domain.TeamEntity.createdBy using @RestResource! (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.UnmodifiableMap["persons"]->java.util.ArrayList[0])"
The error seems to be happening in this class:
@Entity
@Table(name = "team")
public class TeamEntity extends AssignableEntity {
private String name;
private LocalDateTime createdDate;
private LocalDateTime modifiedDate;
private Collection<MembershipEntity> memberships;
private PersonEntity createdBy;
private PersonEntity modifiedBy;
@Basic
@Column(name = "NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Basic
@Column(name = "CREATED_DATE")
public LocalDateTime getCreatedDate() {
return createdDate;
}
public void setCreatedDate(LocalDateTime createdDate) {
this.createdDate = createdDate;
}
@Basic
@Column(name = "MODIFIED_DATE")
public LocalDateTime getModifiedDate() {
return modifiedDate;
}
public void setModifiedDate(LocalDateTime modifiedDate) {
this.modifiedDate = modifiedDate;
}
@OneToMany(mappedBy = "team")
public Collection<MembershipEntity> getMemberships() {
return memberships;
}
public void setMemberships(Collection<MembershipEntity> memberships) {
this.memberships = memberships;
}
@RestResource(rel = "team_createdBy")
@ManyToOne
@JoinColumn(name = "CREATED_BY", referencedColumnName = "ASSIGNABLE_ID", nullable = false)
public PersonEntity getCreatedBy() {
return createdBy;
}
public void setCreatedBy(PersonEntity createdBy) {
this.createdBy = createdBy;
}
@RestResource(rel = "team_modifiedBy")
@ManyToOne
@JoinColumn(name = "MODIFIED_BY", referencedColumnName = "ASSIGNABLE_ID", nullable = false)
public PersonEntity getModifiedBy() {
return modifiedBy;
}
public void setModifiedBy(PersonEntity modifiedBy) {
this.modifiedBy = modifiedBy;
}
}
Ironically, I am not accessing this specific resource. I also have other resources with createdBy
and modifiedBy
-- is it the one causing this issue?
I suspect that you might have exported = false
on your PersonEntity
object. Because of this, any references in PersonEntity
will be added to the _links
section of your TeamEntity
. Because both PersonEntity
objects have a createdBy
reference, they are colliding with the TeamEntity.createdBy
reference.
To understand what is happening this example might help:
class Answer {
Question q; //JPA ManyToOne back-reference
}
class Question {
List<Answer> as; // JPA OneToMany reference
}
class UserAnswer {
Answer a;
Question q;
}
In my case, because an Answer
can only exist within a Question
, we have the following on our AnswerResource
, to prevent Answers from being exported:
@RestResource(exported = false)
This causes Answer
objects to be serialized within the parent object, rather than as a reference in the _links
section, and this ends up being the cause of the problem....
When UserAnswer
is serialized, it renders something like this:
{
"answer" : {
"creationDate" : "2014-09-18T17:28:31.000+0000",
"modificationDate" : "2014-09-18T17:28:31.000+0000",
"answerText" : "Vendas",
},
"_links" : {
"self" : {
"href" : "http://localhost:9090/data/userAnswers/15"
},
"question" : {
"href" : "http://localhost:9090/data/userAnswers/15/question"
}
}
}
Note that "_links.question" above is from the Answer
!
So if you add a Question
to UserAnswer
, you will see the error you are asking about, because the UserAnswer
itself also wants to include a _link reference to a Question
.
In your case, I think your PersonEntity
and your TeamEntity
both have createdBy
references.
I'm not 100% sure what the solution is yet, I don't know if you can specify hierarchical rel
names.
Short answer: Add Spring Data repositories for ALL (or at least more of) your entities. (In this case, it sounds like you need to make a PersonRepository).
Long answer:
Spring Data Rest uses _links to avoid sending back the entire JSON tree, but it can only make _links to mapped entities that have Repositories.
If there isn't a repository for an entity, Spring can't use a link and will instead just put the whole JSON object in the response.
I THINK what's happening with this exception is that a lower, second level relationship is being put into a _link, and more than one of these have the same name.
I'm not 100% sure I understand it all, but I had the same exception when only had repositories for a few entities, and when I made a Repository for every single entity the problem vanished.
链接地址: http://www.djcxy.com/p/22806.html