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

我有一个关键的代码部分,我需要使用悲观锁通过 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);

问题是关于跳过缓存而不是锁定。


慕盖茨4494581
浏览 153回答 2
2回答

慕尼黑的夜晚无繁华

我刚刚getReference在EntityManager其中找到了一个获取实例的方法,该实例的状态可能会被延迟获取。如文档中所述:获取一个实例,其状态可能会被延迟获取。如果请求的实例在数据库中不存在,则在第一次访问实例状态时抛出 EntityNotFoundException。(当调用 getReference 时,允许持久性提供程序运行时抛出 EntityNotFoundException。)应用程序不应期望实例状态在分离时可用,除非它在实体管理器打开时由应用程序访问。作为在一个查询中通过 id 查找和锁定最新实体的一种可能解决方案,我们可以使用以下代码:MyEntity entity = entityManager.getReference(MyEntity.class, key); entityManager.refresh(entity, LockModeType.PESSIMISTIC_WRITE);此查询将创建一个实体(无数据库查询),然后刷新并锁定该实体。

翻翻过去那场雪

为什么不直接将请求的锁与查询本身一起传递呢?MyEntity entity = entityManager.find(MyEntity.class, key, LockModeType.PESSIMISTIC_WRITE);据我了解,这正是您想要的。(文档)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java