2016-09-29 90 views
0

我有有以下类似的关系实体Hibernate项目:开球事件发生后中的多个对象的Hibernate事务更新

Car { 
    String name; 
    Engine engine; 
} 

Engine { 
    String name; 
} 

我们有一个外部系统(Web服务,一个黑盒子),这需要与上述实体所做的更改进行更新,但是,外部系统不会使CarEngine之间的区别:

RemoteCar { 
    String name; 
    String engineName; 
} 

同步过程涉及获得的实例,更新从CarEngine更改的值,然后发送更新请求。

我试图用一个PostUpdateEventListenerrequiresPostCommitHanding返回true揭开序幕的应用程序事件更新外部系统,但如果Car的名字和Engine的名字都在同一事务的更新,我收到两个事件,开始与外部系统的两个同步。

有没有办法确保我只接收我需要的事件?可悲的是Engine的一些更新是直接执行的(EngineDao.get(1).setName()),这意味着Car从未涉及 - 我可以轻松地工作我的方式备份树以获得我的Car实例,但我不知道如何判断是否更新到EngineCar的更大更新或Engine的自包含更新的一部分。

回答

1

我建议不要在每个侦听器回调中与远程系统同步,因为如上所述,它会成为潜在的I/O瓶颈。相反,我会建议维护一个特定于事务的缓存并复制一次。

PostUpdateEventListener火灾,这样做如下:

  1. 检查当前的事务有一个缓存。如果没有,请创建缓存并在提交事务回调之前注册一个(稍后)。
  2. 对于每个更新事件,请检查缓存以查看是否已获取相应的RemoteCar。如果有,请相应地更新缓存。如果它不在缓存中,则从远程系统获取并更新缓存实例。

在事务的提交阶段,会触发before commit事务回调,它会迭代缓存实例并根据您的API,向您的远程系统发送批量更新(1个I/O调用)更新所有修改的RemoteCar实例。

这将允许您的用例,其中2个更新触发2个同步点,以减少到单个远程获取,2个本地更新和1个复制更新回到外部系统。

+0

谢谢你。你将如何管理你的缓存?我可以使用具有PostUpdateEvent.getSession()。getTransaction()作为IdentityHashMap中的键值的Map吗? (当然,正确同步) – Rich

+0

是的,这正是我在管理与Envers中的休眠会话有关的审计进程缓存时所做的。 – Naros