Hibernate checks the state of entities when committing transactions. This is useless and performance-critical when fetching large amounts of data to send to the client.
I found a solution with
entityManager.setFlushMode(FlushModeType.COMMIT);
I put back auto
after the query.
Are there any normal more compact solutions.
Now I'm thinking of doing something similar to aspectJ so I don't clutter up the code and I can annotate both the service and the repository. What do you think about this and how do you solve such a problem?
Example:
@Override
public Collection<ZoomCallInfoDTO> findZoomCalls(Collection<ContactId> invitedUsers, String name, Date startTime, Date endTime, int offset, int limit, boolean asc, callId callId)
{
// Why we did it?
// Due to bad logic of finding calls in time interval (ZoomCallRepository#findAllByProfileAndcallWithinRange)
// which loaded all calls for user to compute periodical calls there are TOO many entities in hibernate.
// So during converting calls to DTOs we also have N x M queries (N - number of call to return, M - number of queries for each call conversion).
// Each query makes hibernate checks all loaded entities for autoFlush policy. And we have bad performance ((
// Possible decisions:
// 1. Switch off autoFlush policy for GET methods:
// 1.1 - Use readOnly transaction (not good for us now because stating top transaction logic is not managed)
// 1.2 - Set flushMode manually (not good as persistence decision but the cheapest now) - CURRENTLY USED
// 2. Decrease number of loaded to hibernate entities - it need to redesign logic of computing periodical calls
// 3. Merge of 1 and 2 decisions - SHOULD BE IMPLEMENTED IN FUTURE
entityManager.setFlushMode(FlushModeType.COMMIT);
if (invitedUsers != null && !invitedUsers.isEmpty())
{
throw new RuntimeException("Search by invited users is not supported.");
}
UserProfile profile = callUtil.getCurrentUserProfile();
List<ZoomCallInfoDTO> callDTOs = new ArrayList<>();
Map<callId, callCacheItem> callCache = new HashMap<>();
for (ZoomCall call : ZoomCallRepository.findAllByProfileAndcallWithinRange(profile.getId(), name, startTime, endTime, offset, limit, asc, callId))
{
callDTOs.add(create(call, profile.getId(), callCache));
}
entityManager.setFlushMode(FlushModeType.AUTO);
return callDTOs;
}
I noticed that after such operations there is an "autoflush" there are too many of them