When an existing user makes a request the method first deletes the oldest record before saving the new request. The code below works fine IF the requests don't come in too rapidly (using an Oracle DB).
public Request saveRequest(Request req)
{
String user = req.getUser();
// Do a NamedQuery on the entity to pull all requests for user
List<Request> requestList = getRequests(user);
LOGGER.info("Request List size is " + requestList.size() + " for " + user);
// Sort the list then delete the first/oldest request
Comparator<Request> bySessionDate = Comparator.comparing(Request::getDate);
Collections.sort(requestList, bySessionDate);
LOGGER.info("Deleting request id " + requestList.get(0).getId());
deleteById(requestList.get(0).getId());
Request sreq = requestRepository.create(req);
LOGGER.info("Saved request for user " + sreq.getUserId());
return sreq;
}
Output:
2021-01-20 00:39:12,167 INFO [beez.service.RequestManager] (default task-4) Request List size is 250 for Bob
2021-01-20 00:39:12,168 INFO [beez.service.RequestManager] (default task-4) Deleting request id 757A9B21E51D49199F2E182F68BC6BF7
2021-01-20 00:39:12,171 INFO [beez.service.RequestManager] (default task-4) Deleted: 757A9B21E51D49199F2E182F68BC6BF7
2021-01-20 00:39:12,173 INFO [beez.service.RequestManager] (default task-4) Saved request for user Bob
2021-01-20 00:39:15,375 INFO [beez.service.RequestManager] (default task-3) Request List size is 250 for Bob
2021-01-20 00:39:15,375 INFO [beez.service.RequestManager] (default task-3) Deleting request id 27239B85472C45EDA5495E98523295F3
2021-01-20 00:39:15,377 INFO [beez.service.RequestManager] (default task-3) Deleted: 27239B85472C45EDA5495E98523295F3
2021-01-20 00:39:15,380 INFO [beez.service.RequestManager] (default task-3) Saved request for user Bob
However, if the user were to submit requests in a very quick fashion, i.e. happy clicker, the same code generates a StaleStateException error.
2021-01-20 00:42:31,307 INFO [beez.service.RequestManager] (default task-3) Request List size is 250 for Bob
2021-01-20 00:42:31,307 INFO [beez.service.RequestManager] (default task-3) Deleting request id 55E43DF4D83E4BF5AD73DE47A49B0DA9
2021-01-20 00:42:31,310 INFO [beez.service.RequestManager] (default task-3) Deleted: 55E43DF4D83E4BF5AD73DE47A49B0DA9
2021-01-20 00:42:31,313 INFO [beez.service.RequestManager] (default task-3) Saved request for user Bob
2021-01-20 00:42:31,332 INFO [beez.service.RequestManager] (default task-7) Request List size is 250 for Bob
2021-01-20 00:42:31,332 INFO [beez.service.RequestManager] (default task-7) Deleting request id 55E43DF4D83E4BF5AD73DE47A49B0DA9
2021-01-20 00:42:31,492 ERROR [org.jboss.as.ejb3.invocation] (default task-7) WFLYEJB0034: EJB Invocation failed on component RequestManager for method public beez.entity.RequestManager service.RequestManager.saveRequest(beez.entity.RequestManager): javax.ejb.EJBTransactionRolledbackException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
.
.
.
Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
Seems like the code hasn't had time to complete the change before the next one came in causing the code to try to delete the same record twice. Other than changing the front end or something else before this method, is there a way around this?
I've tried the @Transactional and @Lock options with no success. Spent a lot of time in this thread but the solutions either didn't work or didn't apply: Hibernate - Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1