当现有用户发出请求时,该方法首先删除最古老的记录,然后再保存新请求。如果请求不太快(使用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;
}输出:
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但是,如果用户以非常快的方式提交请求,即愉快的单击,那么相同的代码将生成一个StaleStateException错误。
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似乎在下一个代码出现之前,代码还没有时间完成更改,导致代码尝试删除同一条记录两次。除了在此方法之前更改前端或其他东西之外,还有什么方法可以绕过吗?
我尝试过“事务处理”和“锁定”选项,但没有成功。在这个线程中花费了大量时间,但是这些解决方案要么不起作用,要么不适用:Hibernate - Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1
发布于 2021-01-20 02:59:13
如果用户点击速度不快,强烈建议您考虑在前面删除API请求,以跳过请求/事件。
正如您所说的,由于加载到单个会话的实体与数据库的当前状态不一致,所以出现了正确的问题。
这可以通过多种方式解决,比如使用悲观锁定(select for update)和性能瓶颈,同步方法.等
处理此问题的最简单方法是使用JPA查询进行删除,并在数据库级别进行排序,因此这始终适用于记录表的当前状态。
delete from request where id= (select req.id from request req left join user usr on usr.id = req.userId where usr.userId=? order by req.date LIMIT 1)请根据您的实体设计更正上述查询。
https://stackoverflow.com/questions/65801968
复制相似问题