2017-08-28 68 views
0

我正在使用具有使用ECache配置的休眠功能的broadleaf演示应用程序。我也有一个外部应用程序,它直接与相同的数据库进行交互。 当我使用外部应用程序更新数据库时,我的broadleaf应用程序不知道这些更改会在创建新实体时抛出重复的主键。我试图通过定期清除休眠缓存来解决这个问题,这使得休眠从头开始构建缓存,因此一切都会同步。 我正在使用以下代码清除二级缓存。无法清除休眠缓存

Cache cache = sessionFactory.getCache(); 
String entityName = "someName"; 
cache.evictEntityRegion(entityName); 

但是,这似乎并不奏效。

我甚至尝试使用JMX监听器手动清除cahche,如visualvm。但这也行不通。我仍然在API中获得旧的主键值。这是因为只有二级缓存正在被清除而离开一级缓存?我被困在这里。任何人都可以帮助解决这个问题吗?

更新: 比方说,我有应用一个。 A使用broadleaf,B使用原始SQL查询插入到db中。我使用应用程序A创建了几个订单,然后使用应用程序B直接在数据库中插入几个订单,并使用max(order_id)+ 1更新SEQUENCE_GENERATOR表。之后,当我尝试使用应用程序A创建订单时,它会引发重复的主键例外。我试图调试到问题,我发现IdOverrideTableGenerator仍然给我旧的主键。这让我对二级缓存感到好奇。不是broadleaf使用SEQUENCE_GENERATOR用于启动主键生成引用并在缓存中维护当前状态?在我的情况下,即使更新SEQUENCE_GENERATOR也不能确保新的唯一主键。

+0

max(order_id)方法不起作用。 OrderImpl的默认增量大小为50。在从应用程序B插入记录之前,您需要事先预定一批ID(例如,其中50个)。这可以保证应用程序A在它请求另一批次时不会使用任何这些ID,并且它保证应用程序B不会使用运行应用程序A的实例中的任何当前保留的ID。还有一点很重要,那就是有一些锁定方法,应用程序B的预订不会意外分享。 – mbvcomeback

+1

不是直接进入数据库手动插入订单,而是在Broadleaf一侧构建一个API端点,将您的其他系统的订单转换为Broadleaf'Order',然后保持该状态,这是一种更好的模式。然后,您可以完全避免整个sequence_generator问题,同时可以更好地分离两个系统。 – phillipuniverse

+0

我同意菲利普。如果您的设计要求允许,最好的办法是创建一个接受订单信息并保留订单的API端点。 – mbvcomeback

回答

2

如果您希望您的实施在运行时识别新实体,则说明您需要对外部导入使用L2高速缓存失效。否则,您将不得不等待缓存区域上配置的TTL过期以便应用程序查看新记录。

但是,在Broadleaf的情况下,L2缓存与Hibernate如何确定主键没有任何直接关系。 Broadleaf利用表生成器策略以高性能和集群安全的方式获取一批ID。您可能会注意到您的模式中有一个名为SEQUENCE_GENERATOR的表。该表包含已为不同的域类获取的各种id范围。每当Hibernate需要为插入操作获取一批新的ID时,它将与该表交互以注册一个新的ID范围以检出。这应该保证群集中的任何节点都不会尝试插入具有冲突ID的实体。

对于您的情况,您需要保证外部进程可以以非冲突方式执行插入。为此,我相信你需要为外部进程创建一个API来调用它,它将代表该调用进程执行相同的“id checkout”操作。然后,您的导入代码(可能位于其他地方)将包含一系列可以安全使用的ID。支持您创建的API的代码应执行与Hibernate通常执行的操作相同的操作,以获取一批用于实体插入的ID。您可以查看org.hibernate.id.enhanced.TableGenerator获取这个样子的例子,并为您自己的目的创建类似的东西。

+0

我只是想补充一点,并不是所有的框架类都使用hibernate生成器CustomerImpl,但实际上并没有。它使用IdGenerationService – John

+0

很好的答案。关键在于,当您更新数据库中的记录时,还需要更新'SEQUENCE_GENERATOR'中的ID范围。 @约翰是正确的,'BLC_ID_GENERATION'是'CustomerImpl'。 这里是'BLC_PRODUCT'的MySQL示例。如果还没有'ProductImpl'键,这也适用。你可以在直接插入一组产品后运行这个'SET @id =(SELECT MAX(product_id)+ 1 FROM blc_product); INSERT INTO sequence_generator(ID_NAME,ID_VAL)VALUES('ProductImpl',@id)ON DUPLICATE KEY UPDATE id_val = @id;' – phillipuniverse

+0

@phillipuniverse我已经更新了SEQUENCE_GENERATOR表中的相应实体值。仍然我从IdOverrideTableGenerator获得旧生成的主键。 – amanraj