簡體   English   中英

如何在Spring Boot中使用Hibernate / JPA返回多級json

[英]How can I return multi-level json using Hibernate/JPA in Spring Boot

我有一個Postgres數據庫,有4個表父母,子女,團體和Group_Membership。

群組可以有多個父母,父母可以有多個群組。 父母可以有多個孩子,但孩子只能有一個孩子。

這是模式的愚蠢版本。 在此輸入圖像描述

我正在使用Spring Boot和Hibernate JPA。

Parent.java

@Entity
@Table(name = "parents")
public class Parent {
    @Id
    @GeneratedValue
    @Column(name="parent_id")
    private Long parentId;
    @Column(name= "first_name")
    private String firstName;
    @Column(name= "last_name")
    private String lastName;
    @OneToMany(mappedBy="parent")
    private Set<Child> children;
    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
            name= "Group_Membership",
            joinColumns = { @JoinColumn(name = "parent_id") },
            inverseJoinColumns = { @JoinColumn(name = "group_id") }
    )
    private Set<Group> groups = new HashSet<>();

    //Constructor 
    //Getters and Setters
}

Child.java

@Entity
@Table(name = "children")
public class Child {
    @Id
    @GeneratedValue
    @Column(name= "child_id")
    private Long childId;
    @Column(name= "first_name")
    private String firstName;
    @Column(name= "last_name")
    private String lastName;
    @ManyToOne
    @JoinColumn(name="parent_id", nullable=false)
    private Parent parent;

    //Constructor 
    //Getters and Setters
}

Group.java

@Entity
@Table(name = "groups")
public class Group {
    @Id
    @GeneratedValue
    @Column(name= "group_id")
    private Long groupId;
    private String name;
    @ManyToMany(mappedBy = "groups")
    private Set<Parent> parents = new HashSet<>();

    //Constructor 
    //Getters and Setters
}

我有所有這些設置的存儲庫:

public interface GroupRepository extends PagingAndSortingRepository<Group, Long> {
    @RestResource(rel = "name-contains", path = "containsName")
    Page<Group> findByNameContains(@Param("name") String name, Pageable page);
}

集團成員表

CREATE TABLE GROUP_MEMBERSHIP (
  PARENT_ID INT NOT NULL,
  GROUP_ID INT NOT NULL,
  PRIMARY KEY (PARENT_ID, GROUP_ID),
  CONSTRAINT GROUP_MEMBERSHIP_IBFK_1
   FOREIGN KEY (PARENT_ID) REFERENCES PARENTS (PARENT_ID),
  CONSTRAINT GROUP_MEMBERSHIP_IBFK_2
   FOREIGN KEY (GROUP_ID) REFERENCES GROUPS (GROUP_ID)
);

當我去http:// localhost:8080 / groups

我收到了這個回復:

{
  "_embedded": {
    "groups": [
      {
        "name": "Hyde Park",
        "_links": {
          "self": {
            "href": "http://localhost:8080/groups/1"
          },
          "group": {
            "href": "http://localhost:8080/groups/1"
          },
          "parents": {
            "href": "http://localhost:8080/groups/1/parents"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://localhost:8080/groups"
    },
    "profile": {
      "href": "http://localhost:8080/profile/groups"
    },
    "search": {
      "href": "http://localhost:8080/groups/search"
    }
  },
  "page": {
    "size": 20,
    "totalElements": 1,
    "totalPages": 1,
    "number": 0
  }
}

然后當我想看看小組中的父母時,我會去http:// localhost:8080 / groups / 1 / parents

響應

{
  "_embedded": {
    "parents": [
      {
        "firstName": "Cherice",
        "lastName": "Giannoni",
        "_links": {
          "self": {
            "href": "http://localhost:8080/parents/1"
          },
          "parent": {
            "href": "http://localhost:8080/parents/1"
          },
          "groups": {
            "href": "http://localhost:8080/parents/1/groups"
          },
          "children": {
            "href": "http://localhost:8080/parents/1/children"
          }
        }
      },
      {
        "firstName": "Aylmer",
        "lastName": "Feckey"
        "_links": {
          "self": {
            "href": "http://localhost:8080/parents/2"
          },
          "parent": {
            "href": "http://localhost:8080/parents/2"
          },
          "groups": {
            "href": "http://localhost:8080/parents/2/groups"
          },
          "children": {
            "href": "http://localhost:8080/parents/2/children"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://localhost:8080/groups/1/parents"
    }
  }
}

最后,當我想看到組中第一個父母的孩子時,我會去http:// localhost:8080 / parents / 1 / children

響應

{
  "_embedded": {
    "children": [
      {
        "firstName": "Richard",
        "lastName": "Giannoni"
        "_links": {
          "self": {
            "href": "http://localhost:8080/children/2"
          },
          "child": {
            "href": "http://localhost:8080/children/2"
          },
          "parent": {
            "href": "http://localhost:8080/children/2/parent"
          }
        }
      },
      {
        "firstName": "Deeanne",
        "lastName": "Giannoni"
        "_links": {
          "self": {
            "href": "http://localhost:8080/children/1"
          },
          "child": {
            "href": "http://localhost:8080/children/1"
          },
          "parent": {
            "href": "http://localhost:8080/children/1/parent"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://localhost:8080/parents/1/children"
    }
  }
}

我希望能夠調用一個端點,如http:// localhost:8080 / groups / search / findAllGroupMembers?group_id = 1

並讓它返回組中的多級json,組中的所有父母以及每個父母的所有孩子。

我知道如何使用子查詢編寫查詢以返回此信息,但我只是好奇是否有更多的“JPA / Hibernate”方法來執行此操作?

謝謝!

編輯:修復使用Alan Hay的答案

GroupFullProjection.java

@Projection(name = "groupFullProjection", types = {Group.class})
public interface GroupFullProjection {
    Long getGroupId();
    String getName();
    Set<ParentFullProjection> getParents();
}

ParentFullProjection.java

@Projection(name = "parentFullProjection", types = {Parent.class})
public interface ParentFullProjection {
    Long getParentId();
    String getFirstName();
    String getLastName();
    Set<Child> getChildren();
}

json回復所有必需的信息

端點: http:// localhost:8080 / groups / 1?projection = groupFullProjection

{
  "name": "Hyde Park",
  "groupId": 1,
  "parents": [
    {
      "children": [
        {
          "firstName": "Richard",
          "lastName": "Giannoni",
        },
        {
          "firstName": "Deeanne",
          "lastName": "Giannoni",
        }
      ],
      "parentId": 1,
      "firstName": "Cherice",
      "lastName": "Giannoni",
      "_links": {
        "self": {
          "href": "http://localhost:8080/parents/1{?projection}",
          "templated": true
        },
        "groups": {
          "href": "http://localhost:8080/parents/1/groups"
        },
        "children": {
          "href": "http://localhost:8080/parents/1/children"
        }
      }
    },
    {
      "children": [
        {
          "firstName": "Hanson",
          "lastName": "Feckey",
        }
      ],
      "parentId": 2,
      "firstName": "Aylmer",
      "lastName": "Feckey",
      "_links": {
        "self": {
          "href": "http://localhost:8080/parents/2{?projection}",
          "templated": true
        },
        "groups": {
          "href": "http://localhost:8080/parents/2/groups"
        },
        "children": {
          "href": "http://localhost:8080/parents/2/children"
        }
      }
    }
  ],
  "_links": {
    "self": {
      "href": "http://localhost:8080/groups/1"
    },
    "group": {
      "href": "http://localhost:8080/groups/1{?projection}",
      "templated": true
    },
    "parents": {
      "href": "http://localhost:8080/groups/1/parents"
    }
  }
}

Lazy / Eager加載與它完全無關。 應用程序中的REST服務由Spring Data Rest提供,並且了解它的外觀以及如何更改它可能值得學習。

https://docs.spring.io/spring-data/rest/docs/current/reference/html/#repository-resources.fundamentals

基本上,您可以獲得指向關聯的鏈接,因為這些實體具有自己的存儲庫,這些存儲庫作為REST資源公開。 如果未將子/父作為REST資源公開,那么數據將被內聯(因為沒有其他方法可以訪問它們)。

但是,您可以使用Projections來獲取數據的替代視圖。 因此,您可以定義一個內聯關聯的投影。 客戶端可以請求此特定的數據視圖。

例如http:// localhost:8080 / groups / 1?projection = groupFullProjection

這涉及創建一個簡單的接口,該接口定義要在該數據視圖中公開的屬性。

請參閱: https//docs.spring.io/spring-data/rest/docs/current/reference/html/#projections-excerpts

這看起來像是這樣的:

@Projection(name = "parentFullProjecton", types = { Parent.class })
interface ParentFullProjection{

    // inline the child collection
    Set<Child> getChildren();

    // other fields
}

@Projection(name = "groupFullProjection", types = { Group.class })
interface GroupFullProjection{

    //inline the parents collection and use the view which inlines Children
    Set<ParentFullProjecton> getParent();

    // other fields
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM