[英]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提供,并且了解它的外观以及如何更改它可能值得学习。
基本上,您可以获得指向关联的链接,因为这些实体具有自己的存储库,这些存储库作为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.