我有一个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"
}
}
}
我希望能够调用一个endpoint,比如http://localhost:8080/groups/search/findAllGroupMembers?group_id=1
并让它返回组、组中的所有父级以及每个父级的所有子级的多级json。
我知道如何编写带有子查询的查询来返回这些信息,但我只是好奇是否有一种更“JPA/Hibernate”的方法来实现这一点?
谢谢!
编辑:使用Alan Hay的答案修复
集体投射。JAVA
@Projection(name = "groupFullProjection", types = {Group.class})
public interface GroupFullProjection {
Long getGroupId();
String getName();
Set<ParentFullProjection> getParents();
}
rojection.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"
}
}
}
懒惰/急切的加载与此毫无关系。应用程序中的REST服务是由Spring Data REST提供的,了解它为什么会这样以及如何更改它可能是值得学习的。
https://docs.spring.io/spring-data/rest/docs/current/reference/html/#repository-资源。基本原理
基本上,您可以获得到关联的链接,因为这些实体有自己的存储库,它们作为REST响应公开。如果子级/父级未作为REST资源公开,那么数据将被内联(因为没有其他方式访问它们)。
但是,您可以使用投影来获取数据的其他视图。这样你就可以定义一个投影,它可以嵌入Assocation。客户端可以请求数据的这种特定视图。
例如http://localhost:8080/groups/1?projection=groupFullProjection
这涉及到创建一个简单的接口,定义要在该数据视图中公开的属性。
见:https://docs.spring.io/spring-data/rest/docs/current/reference/html/#projections-节选
这可能看起来像:
@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
}
我正在实现一个基于实体属性值的持久化机制。所有数据库访问都是通过Hibernate完成的。我有一个包含节点路径的表,它非常简单,只有一个id和一个路径(字符串)。路径数量很少,大约几千条。 主表有数百万行,我没有重复路径,而是将路径规范化为它们自己的表。以下是我在插入主表时想要的行为 1)检查路径表中是否存在路径(通过实体管理器查询,使用路径值作为参数) 2) 如果不存在,则插入并获取id(通过实
我希望在spring boot中返回类似以下内容的json响应: 我的RestController如下所示 但我得到的反应是这样的
问题内容: 我有一个包含列表的类,并使用一对多的映射将其映射,如下所示: 这些Order还具有一个,用于根据以下条件进行过滤: 这可以正常工作,并且结果符合预期。 现在是我的问题:为什么当我将访存类型显式设置为时EAGER,Orders在结果列表中出现多次? 我如何更改我的标准代码才能在新设置下达到相同的结果? 问题答案: 如果我正确理解你的配置,这实际上是预期的行为。 你Order在任何结果中都
问题内容: 在我看来,对多租户的支持现在已经hibernate了将近六个月,此后至少更新了一次。 在JPA之外获得多租户会话看起来相当琐碎: 但是,如何在通过JPA使用hibernate的应用程序中启用它呢?(如果可能的话)。 提前致谢。 问题答案: 您可以通过persistence.xml中的属性对其进行配置,如下所示: 如果使用SCHEMA,则不需要多租户策略。 您还可以在代码中设置这些属性,
问题内容: 我正在使用JPA 2.0并hibernate。我有一个用户类和一个组类,如下所示: 然后,我创建一个用户和组,然后将该用户分配给该组。 我要拥有的是删除组时(当然),该组将被删除,并且该组具有的所有用户-组关系将从USER_GROUP连接表中自动删除,但用户本身不会从USER表。 使用上面的代码,当我删除组时,只有GROUP表中的行将被删除,并且用户在USER_GROUP连接表中仍然具
我需要一个概念来设计一个使用Spring boot、Hibernate和JPA的多数据库应用程序。 目前我正在考虑支持4个关系数据库(Mysql,H2,SQLLite,Oracle)。 我所做的是使用spring boot profile特性选择正确的数据库profile,然后加载相关的数据库属性。