1

我有一个对象 GeneralKnowledgeTest,它包含很多统计字段(ratingsCount、responsesCount、ratingStars ...),每次用户进行该测试时都会更新这些字段(takeTest() -> 事务方法)。

可能会发生许多用户在同一时间进行相同的测试,所以我正在考虑实现一个乐观锁定(@version)和一个拦截器,在抛出乐观锁定异常的情况下重试 takeTest 方法。

所以,在 takeTest 方法中,我总是得到一个新的 GeneralKnowledgeTest 实例,例如entityManager.find(testId),然后更新它的统计字段。如果抛出乐观异常,拦截器将简单地重试 takeTest 方法,直到它成功。

您对此程序有何看法。对于可能有很多用户尝试进行相同测试的系统,这是实现乐观锁定的好方法吗?

PS。如果抛出乐观锁异常,业务不会承认显示任何警告消息,所以拦截器是必须的,以允许顺利执行......

4

2 回答 2

0

我假设这些统计信息仅在测试结束时更新,并且测试需要合理的时间来运行,因此这将降低乐观锁失败的可能性。此外,用户是否有可能因为在设定的时间开始测试而突然完成测试?这会增加锁失败的可能性。

如果吞吐量使得并发更新仍然可能,那么您最好在内存中聚合统计信息(以线程安全的方式)并定期将它们写入数据库。

于 2011-03-01T20:27:38.467 回答
0

这听起来像是一种有效的方法:

Hibernate 在刷新时检查实例版本,如果检测到并发修改则抛出异常。由开发人员来捕获和处理此异常。常见选项是用户有机会合并更改或使用非陈旧数据重新启动业务对话。

您还可以查看将 IsolationLevel 设置为 SERIALIZED 或锁定表行。

另一种选择可能是分离对象,使用传入的统计信息对其进行更新,然后使用调度程序等重新附加(更新)它。但是,这可能需要同步您的服务方法(更新统计信息),并且由于该服务可能是代理的,我认为同步它是不可能的。

于 2011-03-01T20:35:33.950 回答