我有以下三个实体:-
Parent.java:
@实体@Getter公司@设置器@ToString(目标字符串)公共类父类{@身份证@GeneratedValue(策略=GenerationType.INDITY)private Long parentId;private字符串字段;私有字符串字段NotInProjection;@一对多(mappedBy=“parent”)私人列表<儿童>儿童;}
子.java:
@实体@Getter公司@设置程序@到字符串公共课儿童{@身份证@GeneratedValue(策略=GenerationType.INDITY)私人Long childId;私有字符串字段;私有字符串字段NotInProjection;@多对一@JoinColumn(name=“parent_id”)私人父母;@一对多(mappedBy=“父亲”)私有列表<GrandChild>grandChildren;}
孙子.java:
@实体@Getter公司@设置器@ToString(目标字符串)公务舱孙子{@身份证@GeneratedValue(策略=GenerationType.INDITY)私人Long grandChildId;私有字符串字段;私有字符串字段NotInProjection;@多对一@JoinColumn(name=“父id”)私生子父亲;}
它们之间的关系如下:
父级--1-N-<子级--1-N-<孙子级
我希望将我的结果投影到以下dto类中:-
加入Dto.java:
@等于和哈希码@所有ArgsConstructor类JoinedDto{private String parentField;私有列表<ChildWithGrandChildDto>childrenAndGrandChilldren;}
ChildWithGrandChildDto.java:(在dto内部使用)
@所有ArgsConstructor@等于和哈希码带孙子女的班级{private字符串childField;私有列表<String>grandChildFields;}
我希望hibernate继续使用单个特定的最小查询,只包含必需的字段和连接,如下所示:-
选择p1_0.父亲id,p1_0.字段,c1_0.儿童id,c1_0.字段,gc1_0.字段从父级p10左连接子c1 0在p1_0.parent_id=c1_0.parent_id上左连接grand_child gc1_0级关于c1_0.child_id=gc1_0.父亲_id
在上面的查询中,我们可以看到字段字段_非_投影
不返回表的,因为我们不想在dto中使用它们。
在dto中父id
和子id
不存在,但我在上面的查询中返回它们,以便在下面的映射方法中使用它们。但对于需要作为dto发送的实际数据,它们是多余的,如果可能的话,不应包含在上述查询中。
我现在正在使用以下代码实现它:-
在我的存储库中,我使用基于接口的投影来获取原始行的列表,这些行是使用联接查询返回的
公共接口ParentRepository扩展了JpaRepository<Parent,Long>{@查询(“SELECT p.parentId as parentId,”+“p.field作为parentField,”+“c.childId作为childId,”+“c.field AS childField,”+“gc.field AS grandChildField”+“从父级p”+“左加入p.childrens c”+“LEFT JOIN c.grandChildren gc”)列表<JoinedRow>findAllJoinedRows();接口JoinedRow{长getParentId();字符串getParentField();长的getChildId();字符串getChildField();字符串getGrandChildField();}}
内部返回数据示例列表<JoinedRow>
:
![返回数据示例](https://i.sstatic.net/65AqKOfB.png)
现在我使用以下自定义帮助器方法将这些原始行手动映射到dto已加入D
(开头提到):-
//将投影原始表行列表接口转换为嵌套JoinedDto对象列表private List<JoinedDto>mapToJoinedD到Stream(List<ParentRepository.JoinedRow>joinedRows){返回joinedRows.流().collect(Collectors.groupingBy(ParentRepository.JoinedRow::getParentId,Collectors.groupingBy(p->p.getChildId()==null-1:p.获取儿童ID())).entrySet().流().map(this::rowEntryToDto).collect(Collectors.toList());}private JoinedD到rowEntryToDto(条目<长,映射<长,列表<JoinedRow>>>p){字符串parentField=p.getValue().values().iterator().next().get(0).getParentField();列表<ChildWithGrandChildDto>childrenWithGrand Children=p.getValue().entrySet().流().filter(q->q.getKey()!=-1).map(条目::getValue).map(q->new ChildWithGrandChildDto(q.get(0).getChildField(),q.stream()).map(ParentRepository.JoinedRow::getGrandChildField).collect(收集器.toList())).collect(收集器.toList());JoinedDto dto=新的JoinedD to(parentField,childrenWithGrandChildren);返回dto;}
我可以使用上面的helper方法映射到加入的数据流()
将从存储库返回的联接原始表行映射到dto列表,如下所示:-
测试数据库关系应用程序测试.java:
@数据JpaTest@AutoConfigureTestDatabase(replace=AutoConfigureTestDatabase.replace.NONE)类TestDbRelationshipsApplicationTests{@自动连线私有ParentRepository;@测试无效joinTest(){列表<ParentRepository。JoinedRow>l=parentRepository.findAllJoinedRws();列表<JoinedDto>dtos=mapToJoinedD到流(l);System.out.println(dtos);}}
有什么方法可以省略将行转换为dto所需的这些帮助器方法,而直接使用jpa/hibernate将从这个极简连接查询返回的数据映射到我的dto中吗?就像方法一样,它映射到实体对象,我希望它映射到我的自定义dto对象,保持上面指定的查询最小化。
谢谢您。
我的PostgreSQL表脚本:
CREATE TABLE父级(parent_id大序列主键,字段VARCHAR(255),字段_非_投影VARCHAR(255));CREATE TABLE子级(child_id大序列主键,字段VARCHAR(255),字段_非_投影VARCHAR(255),parent_id BIGINT REFERENCES父级(parent_id));创建表格grand_child(grand_child_id大序列主键,字段VARCHAR(255),字段_非_投影VARCHAR(255),父id BIGINT REFERENCES子级(child_id));--插入父表插入父项(字段,字段_非_投影)值(“父字段1”,“父字段不在投影1中”),(“父字段2”,“父不在投影2中”),(“父字段3”,“父字段不在投影3中”);--插入子表INSERT INTO子(字段,字段_非_投影,父_ id)值(“子字段1-1”,“子字段不在投影1-1中”,(SELECT parent_id FROM parent WHERE字段=“父字段1”),(“子字段1-2”,“子不在投影1-2中”,(SELECT parent_id FROM parent WHERE字段=“父字段1”),(“子字段2-1”,“子不在投影2-1中”,(SELECT parent_id FROM parent WHERE字段=“父字段2”),(“子字段3-1”,“子不在投影3-1中”,(从父WHERE字段中选择parent_id=“父字段3”),(“子字段3-2”,“子不在投影3-2中”,(SELECT parent_id FROM parent WHERE字段=“父字段3”);--插入grand_child表插入grand_child(字段,字段not_in_prjection,父亲_id)值(“孙子字段1-1-1”,“孙子不在投影1-1-1中”,(SELECT child_id FROM child WHERE字段=“子字段1-1”),(“孙子字段1-1-2”,“孙子不在投影1-1-2中”,(SELECT child_id FROM child WHERE字段=“子字段1-1”),(“孙子字段1-2-1”,“孙子不在投影1-2-1中”,(SELECT child_id FROM child WHERE字段=“子字段1-2”),(“孙子字段2-1-1”,“孙子不在投影2-1-1中”,(SELECT child_id FROM child WHERE字段=“子字段2-1”),(“孙子字段3-1-1”,“孙子不在投影3-1-1中”,(SELECT child_id FROM child WHERE字段=“子字段3-1”),(“孙子字段3-2-1”,“孙子不在投影3-2-1中”,(SELECT child_id FROM child WHERE字段=“子字段3-2”);