可靠地跟踪Hibernate所做的更改

时间:2017-11-12 21:48:59

标签: java hibernate concurrency transactions

我正在使用<{1}}通过

注册
PostUpdateEventListener

以及其他一些侦听器,以便跟踪Hibernate所做的更改。这很完美,但是,我发现有一个问题:

让我们说,为了按registry.appendListeners(EventType.POST_COMMIT_UPDATE, listener) 跟踪一些amount,我只需执行

id
每个 amountByIdConcurrentMap.put(id, amount); 上的

(让我们忽略其他操作)。问题是这个调用在提交之后的某个时间发生了。因此,有两个提交一个接一个地写一个相同的实体,我可以接收错误顺序中的事件,最后存储旧的POST_COMMIT_UPDATE

  • 这真的有可能,还是以某种方式同步操作?
  • 有没有办法预防或至少发现这种情况?

2 个答案:

答案 0 :(得分:2)

不,没有订购保证,因此您必须注意确保手动正确同步。

如果您正在解决的实际问题是实体状态的缓存,并且如果它适合使用相关实体的二级缓存,那么您可以通过启用L2缓存来获得开箱即用的所有内容。

否则,您可以将任务直接从更新侦听器更新到Executor或消息传递系统,而不是直接从更新侦听器更新映射,而是从数据库异步启动新事务和select for update给定ID的数量。然后在同一事务中更新映射,同时在数据库中保存相应的行锁,以便以串行方式完成相同id的映射更新。

答案 1 :(得分:2)

两个问题和稍后的提案

  1. 您确定需要此优化吗?为什么不通过查询来获取写入数据库的数量。是什么让你有理由使用缓存。

  2. 如何确保在将数据写入数据库之前的数量计算正确同步,以便多个线程或可能的节点不使用旧数据来计算数量,从而覆盖结果以后的计算?

  3. 我想你正确处理第2号问题。然后你必须选择:

    1. 悲观锁定,这意味着在提交之前,您可以在没有并发问题的情况下专门更新缓存​​。
    2. 乐观锁定:在这种情况下,您在数据库记录中有一种时间戳或计数器,您也可以将其与金额一起放入缓存中。您可以使用此值来查找最近的值。