【问题标题】:Spring Data Rest: Detected multiple association links with same relation typeSpring Data Rest:检测到具有相同关系类型的多个关联链接
【发布时间】:2014-09-14 10:29:59
【问题描述】:

关于这个问题,我查看了Spring Data Rest Ambiguous Association Exception,但无法让它为我工作。

正如您在下面的代码中看到的那样,我添加了 @RestResource 注释,其中 rel 等于其他值。

与上面的问题类似,POST 请求有效,但 GET 请求抛出关于具有相同关系类型的多个关联链接的异常:

“无法写入 JSON:检测到多个关联链接相同 关系型!消除歧义 @org.springframework.data.rest.core.annotation.RestResource(rel=createdBy, 导出=真,路径=, description=@org.springframework.data.rest.core.annotation.Description(value=)) @javax.persistence.ManyToOne(可选=true,targetEntity=void, 级联=[],获取=渴望) @javax.persistence.JoinColumn(referencedColumnName=ASSIGNABLE_ID, nullable=false,唯一=false,名称=CREATED_BY,可更新=true, columnDefinition=, foreignKey=@javax.persistence.ForeignKey(name=, value=CONSTRAINT, foreignKeyDefinition=), table=, insertable=true) 私人 com.ag.persistence.domain.PersonEntity com.ag.persistence.domain.TeamEntity.created通过使用@RestResource! (通过参考链: org.springframework.hateoas.PagedResources[\"_embedded\"]->java.util.UnmodifiableMap[\"persons\"]->java.util.ArrayList[0]); 嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException:检测到多个 具有相同关系类型的关联链接!消除歧义 @org.springframework.data.rest.core.annotation.RestResource(rel=createdBy, 导出=真,路径=, description=@org.springframework.data.rest.core.annotation.Description(value=)) @javax.persistence.ManyToOne(可选=true,targetEntity=void, 级联=[],获取=渴望) @javax.persistence.JoinColumn(referencedColumnName=ASSIGNABLE_ID, nullable=false,唯一=false,名称=CREATED_BY,可更新=true, columnDefinition=, foreignKey=@javax.persistence.ForeignKey(name=, value=CONSTRAINT, foreignKeyDefinition=), table=, insertable=true) 私人 com.ag.persistence.domain.PersonEntity com.ag.persistence.domain.TeamEntity.created通过使用@RestResource! (通过参考链: org.springframework.hateoas.PagedResources[\"_embedded\"]->java.util.UnmodifiableMap[\"persons\"]->java.util.ArrayList[0])"

这个错误似乎发生在这个类中:

@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;
    }
}

具有讽刺意味的是,我没有访问这个特定的资源。我还有 createdBymodifiedBy 的其他资源——它是导致此问题的原因吗?

【问题讨论】:

  • 是否有其他实体拥有createdBy 属性?例如PersonEntity
  • 我所有的实体都有四个字段:createdBymodifiedBycreatedDatemodifiedDate
  • 这可能是问题所在。看看this question。您的TeamEntity 中的PersonEntitys 都可能公开一个链接createdBy
  • 我需要这些字段进行编辑——有解决方法吗?
  • PersonEntity 和 TeamEntity 有自己的存储库吗?也请粘贴这些类。

标签: java spring spring-mvc spring-data spring-data-rest


【解决方案1】:

我怀疑您的PersonEntity 对象上可能有exported = false。因此,PersonEntity 中的任何引用都将添加到您的TeamEntity_links 部分。因为两个PersonEntity 对象都有createdBy 引用,所以它们与TeamEntity.createdBy 引用发生冲突。

要了解正在发生的事情,此示例可能会有所帮助:

class Answer {
   Question q; //JPA ManyToOne back-reference
}

class Question {
   List<Answer> as; // JPA OneToMany reference
}

class UserAnswer {
   Answer a;
   Question q;
}

在我的例子中,因为Answer 只能存在于Question 中,我们在AnswerResource 上有以下内容,以防止答案被导出:

@RestResource(exported = false)

这会导致Answer 对象在父对象中被序列化,而不是作为_links 部分中的引用,这最终成为问题的原因......

UserAnswer被序列化时,它会呈现如下内容:

{
  "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"
    }
  }
}

请注意,上面的“_links.question”来自Answer

因此,如果您将Question 添加到UserAnswer,您将看到您所询问的错误,因为UserAnswer 本身想要包含对@987654343 的_link 引用@。

就你而言,我认为你的 PersonEntityTeamEntity 都有 createdBy 引用。

我还不能 100% 确定解决方案是什么,我不知道您是否可以指定分层 rel 名称。

【讨论】:

【解决方案2】:

简答:为所有(或至少更多)实体添加 Spring Data 存储库。 (在这种情况下,听起来您需要创建一个 PersonRepository)。

长答案:

Spring Data Rest 使用 _links 来避免发回整个 JSON 树,但它只能使 _links 指向具有存储库的映射实体。

如果没有实体的存储库,Spring 不能使用链接,而是将整个 JSON 对象放入响应中。

我认为这个例外发生的情况是,一个较低的二级关系被放入一个_link,并且其中多个具有相同的名称。

我不是 100% 确定我完全理解了这一切,但是当我只有几个实体的存储库时,我遇到了同样的例外,当我为每个实体创建一个存储库时,问题就消失了。

【讨论】:

    猜你喜欢
    • 2014-08-17
    • 2018-09-04
    • 1970-01-01
    • 2019-12-25
    • 2019-01-29
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 2014-10-08
    相关资源
    最近更新 更多