Spring数据休息和jpa @OneToMany重复“_links”

Posted

技术标签:

【中文标题】Spring数据休息和jpa @OneToMany重复“_links”【英文标题】:Spring data rest and jpa @OneToMany duplicates "_links" 【发布时间】:2017-07-11 05:43:26 【问题描述】:

Spring Data Rest 与 Spring Data JPA 一起使用时遇到问题。我正在使用 Spring-boot 1.4.4.RELEASE。

这是我的 spring-data-rest 存储库:

public interface ProfileJpaRepository extends JpaRepository<Profile, Long> 

这是我的实体(为简洁起见,未显示 getter 和 setter)。

Profile.java:

@Entity
@Table(name = "PROFILE")
public class Profile 

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

    private String description;

    // Don't use mappedBy="profile" because attributes are not persisted properly
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "PROFILE_ID")
    private Set<Attribute> attributes;

    ...

属性.java

@Entity
@Table(name = "ATTRIBUTE")
public class Attribute 

     @Id
     @GeneratedValue(strategy=GenerationType.AUTO)
     @Column(name = "ID")
     private Long id;

     private String uri;

     @ManyToOne(fetch = FetchType.EAGER)
     private Profile profile;

     @ElementCollection(fetch = FetchType.EAGER)
     @CollectionTable(name="ATTRIBUTE_DATAS")
     private List<String> datas = new ArrayList<>();

     public Attribute() 

     public Attribute(String uri, List<String> datas) 
        this.uri = uri;
        this.datas = datas;
    

    ...

“http://localhost:8880/profiles”上的 POST 以创建实体:


    "description" : "description-value",
    "attributes" : [
        
            "uri" : "uri-a",
            "datas" : ["uri-a-value"]
        ,
        
            "uri" : "uri-b",
            "datas" : ["uri-b-value"]
        
    ]

这是我点击http://localhost:8880/profiles时的结果:


  "_embedded" : 
    "profiles" : [ 
      "description" : "description-value",
      "attributes" : [ 
        "uri" : "uri-a",
        "datas" : [ "uri-a-value" ],
        "_links" : 
          "profile" : 
            "href" : "http://localhost:8880/profiles/1"
          
        
      , 
        "uri" : "uri-b",
        "datas" : [ "uri-b-value" ],
        "_links" : 
          "profile" : 
            "href" : "http://localhost:8880/profiles/1"
          
        
       ],
      "_links" : 
        "self" : 
          "href" : "http://localhost:8880/profiles/1"
        ,
        "profile" : 
          "href" : "http://localhost:8880/profiles/1"
        
      
     ]
  ,
  "_links" : 
    "self" : 
      "href" : "http://localhost:8880/profiles"
    ,
    "profile" : 
      "href" : "http://localhost:8880/profile/profiles"
    
  ,
  "page" : 
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 0
  

我认为有一个问题,因为"_links" 在每个属性下都指定了。相反,我会期待这样的事情:


  "_embedded" : 
    "profiles" : [ 
      "description" : "description-value",
      "attributes" : [ 
        "uri" : "uri-a",
        "datas" : [ "uri-a-value" ]
      , 
        "uri" : "uri-b",
        "datas" : [ "uri-b-value" ]
       ],
      "_links" : 
        "self" : 
          "href" : "http://localhost:8880/profiles/1"
        ,
        "profile" : 
          "href" : "http://localhost:8880/profiles/1"
        
      
     ]
  ,
  "_links" : 
    "self" : 
      "href" : "http://localhost:8880/profiles"
    ,
    "profile" : 
      "href" : "http://localhost:8880/profile/profiles"
    
  ,
  "page" : 
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 0
  

请注意,我一直在从 MongoRepository 切换到 JpaRepository,并且使用 MongoRepository,这些 "_links" 没有“重复”。

有人可以对此有所了解吗?我是否在我的 JPA 实体上配置错误?我需要在 rest 存储库上配置一些东西吗?

如果您需要,可以在此处找到有关依赖版本的更多信息,我没有覆盖这些 (http://docs.spring.io/spring-boot/docs/1.4.4.RELEASE/reference/html/appendix-dependency-versions.html)

谢谢。

【问题讨论】:

您知道在您的代码中如何/为什么生成 _links 吗?我假设这发生在 JSON 序列化期间,但我从未使用默认配置遇到过它们。 @TorstenN.,这是由 ProfileJpaRepository 自动完成的,Spring Data Rest 看到它扩展了 JpaRepository 并且它“使用 HAL 作为媒体类型为您的域模型公开一个可发现的 REST API”,自动。 【参考方案1】:

为了解决我一直在使用 Projections 的问题(更多信息在这里:http://docs.spring.io/spring-data/rest/docs/current/reference/html/#projections-excerpts)。发布时我不知道该功能。

我必须注释我的存储库并告诉它使用我的 InlineAttributes 投影:

import org.springframework.data.rest.core.annotation.RepositoryRestResource;

@RepositoryRestResource(excerptProjection = InlineAttributes.class)
public interface ProfileJpaRepository extends JpaRepository<Profile, Long> 

在 Attribute 类上我必须添加 @JsonIgnore 注释:

import com.fasterxml.jackson.annotation.JsonIgnore;

@Entity
@Table(name = "ATTRIBUTE")
public class Attribute 
     ...

     @ManyToOne(fetch = FetchType.EAGER)
     @JsonIgnore
     private Profile profile;

     ...

还有我必须创建的 InlineAttributes 投影类。我指定了顺序,因为它与以前不同:

import org.springframework.data.rest.core.config.Projection;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;    

@Projection(name = "inlineAttributes", types =  Profile.class )
@JsonPropertyOrder( "description", "attributes" )
public interface InlineAttributes 

    public String getDescription();
    public Set<Attribute> getAttributes();

然后您需要在调用其余端点时应用投影:

http://localhost:8880/profiles?projection=inlineAttributes

【讨论】:

以上是关于Spring数据休息和jpa @OneToMany重复“_links”的主要内容,如果未能解决你的问题,请参考以下文章

@OneToMany Spring Boot 2.1.5.RELEASE 中的 Spring Data JPA 没有获取所有数据

Spring JPA OneToMany 集合不删除条目

在 JPA/Hibernate 中使用 @OnetoMany 的实体中不存在时从数据库中删除子记录(Spring 引导应用程序)

spring jpa ManyToMany 理解和使用

Spring数据jpa,关系

onetomany / manytoone 的无限循环?春天/休息api