【发布时间】:2018-04-09 05:34:35
【问题描述】:
我有一个 Postgres 数据库,其中包含 4 个表 Parent、Children、Groups 和 Group_Membership。
组可以有多个父母,父母可以有多个组。父母可以有多个孩子,但孩子只能有一个父母。
我正在使用带有 Hibernate JPA 的 Spring Boot。
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"
}
}
}
【问题讨论】:
-
我认为问题在于父母和孩子都懒加载。尝试急切地加载它。 stackoverflow.com/questions/29602386/…
-
感谢您的链接。我将对 fetchTypes 和 NamedEntityGraph 注释做更多的研究。
-
你用什么来生成 json?你能发布负责的代码吗?
-
Tom,我上面包含的存储库文件会生成 json。最重要的是说“扩展 PagingAndSortingRepository”的部分你也可以扩展 CrudRepository。 docs.spring.io/spring-data/commons/docs/current/api/org/…
标签: java postgresql hibernate jpa spring-boot