48

自定义 JPA 映射器类有一个方法:

removeUser()

1. execute 'DELETE' HQL query to remove user
2. call getEntityManager().flush();
3. call getEntityManager().clear();

如果我理解 clear() 正确,它将从上下文中删除所有持久实体。-资源

但是,我也在这里阅读,

you should define clear architecture- and design guidelines about where a 
clear() can be called. 

关于何时调用 clear() 的明确指导方针是什么?

4

3 回答 3

57

文章对此进行了解释。清除实体管理器会清空其关联的缓存,迫使新的数据库查询稍后在事务中执行。使用事务绑定实体管理器时,几乎不需要清除实体管理器。我认为有两个理由要清除:

  • 在进行批处理时,为了避免由于长时间的脏检查而导致巨大的缓存占用内存并增加刷新时间
  • 当您执行 DML 或 SQL 查询时,它完全绕过实体管理器缓存(如您的示例中所示)。在这种情况下,由于查询,缓存所持有的状态并不能反映数据库中的内容,因此您需要清除缓存以避免这种不一致。
于 2012-12-14T23:25:53.370 回答
7

是的,这完全取决于平台的架构风格作为文档点。

  • 例如,如果在您的应用程序中 EM 是线程关联的,那么事务管理的解决方案之一是实现 Session-Per-Request 模式,该模式在用户请求的每次开始时启动事务,并在请求的每一端提交并清除缓存为了防止脏读。这只是一个简单的例子
  • 另一个示例是在 SOA 平台中。对于每个服务也可以在开始时打开一个事务并在最后提交它并清除(如果其他服务使用相同的 EM 并且需要避免脏读)
  • 我将重播前两种常见情况 - 批处理一种,并在所有可能的情况下绕过 EM。所以在这种情况下,查询将被迫从 DB 中查询,而不是从缓存中查询。
  • 您应该知道您使用的是 L1 和 L2 缓存,而 L1 是 EM 清除的缓存。当您读取大量数据时(应该不是这种情况)(然后还需要在一段时间内进行清除。

如您所见,取决于您平台的案例、架构和风格。直接针对您的方法 - 按方法刷新和清除缓存不是一个好习惯,它是一种反模式方法。

于 2012-12-15T09:49:24.587 回答
0

TL;DR:EntityManager.clear如果您要执行一组 JPA 操作,而您不需要大多数已加载的实体,请使用

我最近遇到了一个性能问题,这促使我询问如何获得额外的日志记录。在我得到答案之前,我发现了如何解决这个问题,并且通过EntityManager.clear().

我使用它的一个用例是隔离可能密集的操作并加载大量实体​​以供实体管理器管理。就我而言,有一个步骤是我执行授权检查。对于其余事务中的大部分业务逻辑,我不需要它会使用的大部分数据(用户配置文件、低级别实体访问检查等)。

我发现即使我不使用它们,它也会在会话的剩余时间内保持不变,即使我的处理已经完成,最终也需要刷新。

通过在clear刷新发生之前执行它,它会从实体管理器中释放它们并且不再受管理。

于 2021-12-30T03:53:46.567 回答