I'm using Spring Boot with Hibernate and JPA.
I have three entities Device
, ErrorType
and ErrorRecord
with relation ship One-to-many (see the figure below).
Now, when I get one device, I want to get its list of errorTypes. For each errorTypes, I want to get the ONLY ONE latest errorRecord if any.
Here is my current code:
ErrorType.java
@Entity
@Table("tbl_error_type")
class ErrorType {
...
@OrderBy(value = "createAt DESC")
@OneToMany(mappedBy = "errorType", cascade = CascadeType.ALL)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<ErrorRecord> errors = new LinkedHashSet<>();
...
}
ErrorRecord.java
@Entity
@Table("tbl_error_record")
class ErrorRecord{
...
@ManyToOne
@JoinColumn(name = "error_type_id")
private ErrorType errorType;
...
}
ErrorTypeRepository.java
@Query("SELECT DISTINCT e FROM ErrorType e LEFT JOIN FETCH e.errors WHERE e.device.id =:deviceId ORDER BY e.errorType")
List<ErrorType> findErrorTypesByDeviceIdEagerErrorRecords(@Param("robotId") UUID robotId);
ErrorTypeService.java
@Transactional(readOnly = true)
public List<ErrorTypeDTO> findAll(UUID deviceId) {
return errorTypeRepository.findErrorTypesByDeviceIdEagerErrorRecords(deviceId).stream().map(errorType -> {
ErrorTypeDTO dto = new ErrorTypeDTO();
// Some getter and setter here
if (errorType.getErrors() != null && !errorType.getErrors().isEmpty()) {
dto.setLatestError(errorType.getErrors().get(0));
}
}).collect(Collectors.toCollection(LinkedList::new));
}
Currently, it works well with data correctly. However, because data in ErrorRecord
increases rapidly, so there could be up to millions of ErrorRecord
for each ErrorType
. In that case, the performance of this API is too slow and timeout.
Expected: I want to load only one records (order by createAt
, limit 1) in the fetched child errors
when load all errorType
.
I could load for all ErrorType
first, and loop through list of errorTypes. For each errorType, make a query to get one latest errorRecords. But it seems a bad performance way, which create a lot of query to database (n+1 problem).
After researching about Hibernate query expression, I still have no idea for limit number of records in child collections.