无法清除休眠缓存
Not able to clear hibernate cache
我正在使用 broadleaf 演示应用程序,它的休眠模式配置了 ECache。我还有一个直接与同一个数据库交互的外部应用程序。
当我使用外部应用程序更新数据库时,我的阔叶应用程序不知道这些更改会在创建新实体时抛出重复的主键。我试图通过定期清除休眠缓存来解决此问题,这使休眠能够从头开始构建缓存,因此所有内容都会同步。
我正在使用以下代码清除二级缓存。
Cache cache = sessionFactory.getCache();
String entityName = "someName";
cache.evictEntityRegion(entityName);
但是,这似乎行不通。
我什至尝试使用 visualvm 等 JMX 侦听器手动清除缓存。但这也行不通。我的 API 中仍然有旧的主键值。这是因为只有二级缓存被清除而留下一级缓存吗?我被困在这里。任何人都可以帮助解决这个问题吗?
更新:
假设我有应用程序 A 和 B。 A 使用阔叶树,B 使用原始 SQL 查询插入数据库。我使用应用程序 A 创建了几个订单,然后我使用应用程序 B 直接在数据库中插入了几个订单,同时我用 max(order_id) + 1 更新了 SEQUENCE_GENERATOR table。之后当我尝试使用应用程序 A 创建订单,它会抛出重复主键异常。我尝试调试发现 IdOverrideTableGenerator 仍然提供我的旧主键的问题。这让我对二级缓存产生了好奇。 broadleaf 不使用 SEQUENCE_GENERATOR 来启动主键生成的引用并在缓存中维护当前状态吗?在我的例子中,即使更新 SEQUENCE_GENERATOR 也不能确保主键是新鲜且唯一的。
你是对的,如果你想让你的实现在运行时识别你的新实体,你需要对你的外部导入进行 L2 缓存失效。否则,您将不得不等待缓存区域上配置的 TTL 过期,您的应用程序才能看到新记录。
但是,在 Broadleaf 的情况下,L2 缓存与 Hibernate 如何确定主键没有任何直接关联。 Broadleaf 利用 table 生成器策略以高性能和集群安全的方式获取一批 ID。您可能注意到架构中有一个名为 SEQUENCE_GENERATOR 的 table。此 table 包含为不同域 类 获取的各种 ID 范围。每当 Hibernate 需要获取一批新的 id 用于插入时,它会与此 table 交互以注册新的 id 范围以进行检查。这应该保证集群中的任何节点都不会尝试插入具有冲突 ID 的实体。
在您的情况下,您需要保证外部进程可以以非冲突方式执行插入。为此,我相信您需要为外部进程创建一个 API 来调用,它将代表该调用进程执行相同的 "id checkout" 操作。然后,您的导入代码(可能位于其他地方)将具有一系列可以安全使用的 ID。支持您创建的 API 的代码应该执行与 Hibernate 通常执行的相同操作,以获取一批用于实体插入的 ID。您可以查看 org.hibernate.id.enhanced.TableGenerator 以了解这是什么样子的示例,并为您自己的目的创建类似的东西。
我正在使用 broadleaf 演示应用程序,它的休眠模式配置了 ECache。我还有一个直接与同一个数据库交互的外部应用程序。 当我使用外部应用程序更新数据库时,我的阔叶应用程序不知道这些更改会在创建新实体时抛出重复的主键。我试图通过定期清除休眠缓存来解决此问题,这使休眠能够从头开始构建缓存,因此所有内容都会同步。 我正在使用以下代码清除二级缓存。
Cache cache = sessionFactory.getCache();
String entityName = "someName";
cache.evictEntityRegion(entityName);
但是,这似乎行不通。
我什至尝试使用 visualvm 等 JMX 侦听器手动清除缓存。但这也行不通。我的 API 中仍然有旧的主键值。这是因为只有二级缓存被清除而留下一级缓存吗?我被困在这里。任何人都可以帮助解决这个问题吗?
更新: 假设我有应用程序 A 和 B。 A 使用阔叶树,B 使用原始 SQL 查询插入数据库。我使用应用程序 A 创建了几个订单,然后我使用应用程序 B 直接在数据库中插入了几个订单,同时我用 max(order_id) + 1 更新了 SEQUENCE_GENERATOR table。之后当我尝试使用应用程序 A 创建订单,它会抛出重复主键异常。我尝试调试发现 IdOverrideTableGenerator 仍然提供我的旧主键的问题。这让我对二级缓存产生了好奇。 broadleaf 不使用 SEQUENCE_GENERATOR 来启动主键生成的引用并在缓存中维护当前状态吗?在我的例子中,即使更新 SEQUENCE_GENERATOR 也不能确保主键是新鲜且唯一的。
你是对的,如果你想让你的实现在运行时识别你的新实体,你需要对你的外部导入进行 L2 缓存失效。否则,您将不得不等待缓存区域上配置的 TTL 过期,您的应用程序才能看到新记录。
但是,在 Broadleaf 的情况下,L2 缓存与 Hibernate 如何确定主键没有任何直接关联。 Broadleaf 利用 table 生成器策略以高性能和集群安全的方式获取一批 ID。您可能注意到架构中有一个名为 SEQUENCE_GENERATOR 的 table。此 table 包含为不同域 类 获取的各种 ID 范围。每当 Hibernate 需要获取一批新的 id 用于插入时,它会与此 table 交互以注册新的 id 范围以进行检查。这应该保证集群中的任何节点都不会尝试插入具有冲突 ID 的实体。
在您的情况下,您需要保证外部进程可以以非冲突方式执行插入。为此,我相信您需要为外部进程创建一个 API 来调用,它将代表该调用进程执行相同的 "id checkout" 操作。然后,您的导入代码(可能位于其他地方)将具有一系列可以安全使用的 ID。支持您创建的 API 的代码应该执行与 Hibernate 通常执行的相同操作,以获取一批用于实体插入的 ID。您可以查看 org.hibernate.id.enhanced.TableGenerator 以了解这是什么样子的示例,并为您自己的目的创建类似的东西。