【发布时间】:2016-02-22 20:48:16
【问题描述】:
假设有这种情况:
我们以标准方式配置了 Spring Data,有一个 Respository 对象,一个 Entity 对象,一切正常。
现在,出于一些复杂的动机,我必须使用EntityManager(或JdbcTemplate,任何级别低于 Spring Data)直接使用本机 SQL 查询更新与我的Entity 关联的表。所以,我没有使用Entity 对象,而只是在我用作实体的表上手动进行数据库更新(更正确地说是我从中获取值的表,请参阅下一行)。
原因是我必须将我的 spring-data Entity 绑定到一个 MySQL 视图,该视图使多个表成为 UNION,而不是直接绑定到我需要更新的表。
会发生什么:
在功能测试中,我调用“手动”更新方法(在创建 MySQL 视图的表上),如前所述(通过实体管理器),如果我做一个简单的Respository.findOne(objectId),我会得到旧的对象(未更新)。我必须调用Entitymanager.refresh(object) 来获取更新的对象。
为什么?
有没有办法在 spring-data 中“同步”(开箱即用)对象(或强制刷新)?还是我在祈求奇迹? 我并不讽刺,但也许我不是那么专家,也许(或可能)是我的无知。如果是这样,请解释我为什么并(如果你愿意)分享一些关于这个惊人框架的高级知识。
【问题讨论】:
-
您是否在同一测试范围内执行更新和提取?
-
在同一个测试中是的。
-
那么(调用
findOne时对象未刷新)是预期的行为。假设您使用 Hibernate 作为 JPA 提供程序(所有 JPA 提供程序的逻辑相同),在单个测试期间使用相同的 HibernateSession和 HibernateSession缓存对象。EntityManager.refresh强制 Hibernate 忽略缓存内容并重新从数据库加载数据。 -
在真实环境(已部署的应用程序)中运行时会发生什么?我想在这种情况下也有一个缓存。我如何(最终)禁用它?
-
如果你的实际代码是
@Transactional ... update(...),然后是Entity fetch(...),那么你就可以了,因为update(你实际执行更新的地方)和fetch(你获取更新的地方data) 位于两个不同的事务边界内,因此不会共享相同的Session,即使它们被称为update(...); Entity entity = fetch(...);。如果它们在同一个事务边界内,那么它们将共享同一个Session,并且您将拥有一个陈旧的对象。
标签: java persistence spring-data spring-data-jpa