为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 EntityManager 通过 id 查找实体而不在一个查询中命中缓存?

如何使用 EntityManager 通过 id 查找实体而不在一个查询中命中缓存?

慕盖茨4494581 2022-05-12 16:43:57
我有一个关键的代码部分,我需要使用悲观锁通过 id 读取和锁定实体。这部分代码现在看起来像这样:MyEntity entity = entityManager.find(MyEntity.class, key);entityManager.refresh(entity, LockModeType.PESSIMISTIC_WRITE);它工作正常,但据我了解,如果休眠缓存中没有实体,我们将使用 2 个读取事务到数据库。第一个事务通过 id 查找实体,另一个事务刷新和锁定实体。在这种情况下是否可以只使用一个事务?我会想象这样的事情:boolean skipCache = true;MyEntity entity = entityManager.find(MyEntity.class, key,     LockModeType.PESSIMISTIC_WRITE, skipCache);但是没有像skipCache. 是否有另一种方法可以使用 id 直接从数据库中读取实体EntityManager?更新:如果实体存在于缓存中,此查询将命中一级缓存。因此,它可能会返回过时的数据,这就是为什么它不适合应该阻止任何读取的关键部分:MyEntity entity = entityManager.find(MyEntity.class, key, LockModeType.PESSIMISTIC_WRITE);问题是关于跳过缓存而不是锁定。
查看完整描述

2 回答

?
慕尼黑的夜晚无繁华

TA贡献1864条经验 获得超6个赞

我刚刚getReferenceEntityManager其中找到了一个获取实例的方法,该实例的状态可能会被延迟获取。如文档中所述:

获取一个实例,其状态可能会被延迟获取。如果请求的实例在数据库中不存在,则在第一次访问实例状态时抛出 EntityNotFoundException。(当调用 getReference 时,允许持久性提供程序运行时抛出 EntityNotFoundException。)应用程序不应期望实例状态在分离时可用,除非它在实体管理器打开时由应用程序访问。

作为在一个查询中通过 id 查找和锁定最新实体的一种可能解决方案,我们可以使用以下代码:

MyEntity entity = entityManager.getReference(MyEntity.class, key);
entityManager.refresh(entity, LockModeType.PESSIMISTIC_WRITE);

此查询将创建一个实体(无数据库查询),然后刷新并锁定该实体。


查看完整回答
反对 回复 2022-05-12
?
翻翻过去那场雪

TA贡献2065条经验 获得超13个赞

为什么不直接将请求的锁与查询本身一起传递呢?

MyEntity entity = entityManager.find(MyEntity.class, key, LockModeType.PESSIMISTIC_WRITE);

据我了解,这正是您想要的。(文档


查看完整回答
反对 回复 2022-05-12
  • 2 回答
  • 0 关注
  • 152 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信