Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
[Java][Hibernate]如何获取子依赖项集合的限制?_Hibernate_Jpa_Jpql - Fatal编程技术网

[Java][Hibernate]如何获取子依赖项集合的限制?

[Java][Hibernate]如何获取子依赖项集合的限制?,hibernate,jpa,jpql,Hibernate,Jpa,Jpql,我将SpringBoot与Hibernate和JPA一起使用 我有三个实体Device、ErrorType和ErrorRecord,它们之间的关系为一对多,如下图所示 现在,当我得到一个设备时,我想得到它的错误类型列表。对于每种错误类型,我只想得到一个最新的错误记录(如果有的话) 这是我目前的代码: ErrorType.java @实体 @表B错误类型 类错误类型{ ... @OrderByvalue=createAt DESC @OneToNameAppedby=errorType,casca

我将SpringBoot与Hibernate和JPA一起使用

我有三个实体Device、ErrorType和ErrorRecord,它们之间的关系为一对多,如下图所示

现在,当我得到一个设备时,我想得到它的错误类型列表。对于每种错误类型,我只想得到一个最新的错误记录(如果有的话)

这是我目前的代码:

ErrorType.java

@实体 @表B错误类型 类错误类型{ ... @OrderByvalue=createAt DESC @OneToNameAppedby=errorType,cascade=CascadeType.ALL @Cacheusage=CacheConcurrentyStrategy.NONSTRICT\u READ\u WRITE 私有集错误=新LinkedHashSet; ... } ErrorRecord.java

@实体 @表B错误记录 类错误记录{ ... @许多酮 @JoinColumnname=错误类型id 私有错误类型错误类型; ... } ErrorTypeRepository.java

@QuerySELECT DISTINCT e FROM ErrorType e LEFT JOIN FETCH e.errors其中e.device.id=:deviceId ORDER BY e.ErrorType 列表findErrorTypesByDeviceIdEagerErrorRecords@ParamrobotIdUUID机器人; ErrorTypeService.java

@TransactionalreadOnly=true 公共列表FindAlluid设备ID{ 返回errorTypeRepository.FinderRorTypesByDeviceId错误记录DeviceId.stream.maperrorType->{ ErrorTypeDTO dto=新的ErrorTypeDTO; //这里有些能手和二传手 如果errorType.getErrors!=null&&!errorType.getErrors.isEmpty{ dto.setLatestErrorerrorType.getErrors.get0; } }.collectCollectors.toCollectionLinkedList::新建; } 目前,它可以正确地处理数据。但是,由于ErrorRecord中的数据增长迅速,因此每个ErrorType中可能有多达数百万个ErrorRecord。在这种情况下,此API的性能太慢且超时

预期:我只想按createAt加载一条记录,加载所有errorType时,在获取的子错误中限制1

我可以先加载所有ErrorType,然后循环遍历ErrorType列表。对于每个errorType,进行查询以获取最新的errorRecords。但这似乎是一种性能不好的方法,这造成了大量对数据库n+1的查询问题


在研究了Hibernate查询表达式之后,我仍然不知道如何限制子集合中的记录数。

从中可以看出,获取最后一条错误记录并不是一项简单的任务。据我所知,使用JPA映射映射这样的东西是不可能的。这更适合于特定的操作,如FinderRorTypesByDeviceIdErrorRecords

同样,这样的查询也不能用JPQL编写,只能用本机SQL编写。例如,使用,它将类似于:

FluentQuery query=FluentJPA.SQLErrorType errorType->{ OrderedErrorRecord orderedRec=子查询错误记录错误记录->{ 别名rn=别名聚合比罗编号 .OVERPARTITIONBYerrorRec.getErrorType.getId .ORDERBYerrorRec.getCreatedAt.DESC, OrderedErrorRecord::getRowNumber; 选择errorrec,rn; FROMerrorRec; }; 与OrderedRec; 选择ErrorType,orderedRec.getErrorDescription; FROMerrorType.LEFT_JOINorderedRec .ONorderedRec.getErrorType==errorType&&orderedRec.getRowNumber==1; 其中ErrorType.getDevice.getId==deviceId; }; 返回query.createQueryem,ErrorTypeWithLastError.class.getResultList; 这将生成以下SQL:

WITH q0 AS 
(SELECT t1.*,  ROW_NUMBER()  OVER(PARTITION BY  t1.error_type_id 
 ORDER BY  t1.created_at  DESC   ) AS row_number 
FROM tbl_error_record t1 )

SELECT t0.*, q0.error_description 
FROM tbl_error_type t0  LEFT JOIN q0  ON ((q0.error_type_id = t0.id) AND (q0.row_number = 1)) 
WHERE (t0.device_id = ?1)
请注意,我选择了其他字段,而不是在ErrorType中声明的字段,因此需要一个DTO投影来映射它们。我们还需要OrderedErrorRecord来保存行号。因此,宣布了另外两个类别:

@元组 @Getter//lombok 公共静态类OrderedErrorRecord扩展了ErrorRecord{ 私有整数行数; } @元组 @Getter//lombok 公共静态类ErrorTypeWithLastError扩展了ErrorType{ @嵌入 私有错误内容错误内容; }