我有一个约10000个对象的列表。
我正在尝试调用一个***mysql更新查询(过程)***,然后在同一个事务中获取更新的对象。这可以实现吗?
当我调用***delete语句+ flush()***时,hib会检索到正确的对象(删除的对象丢失了)。但是当我尝试***update语句+ flush()***时,hib会检索到初始的未更改对象。
@Transactional
void test() {
//...
em.createQuery("delete from StorefrontProduct sp where sp in (:storefrontProducts)")
.setParameter("storefrontProducts", storefrontProductsToDelete)
.executeUpdate();
// example
em.createQuery("update StorefrontProduct sp set sp.orderIndex=0 where sp.id=90")
.executeUpdate();
em.flush();
//Simple JPA query
List<StorefrontProduct> result = repository.findAllByPreviousOrderIndexIsNotNull();
//additional code....
}
运行上述代码并在findAll调用后放置断点后,第一个查询中提供的对象被删除并刷新,但更新查询未刷新。
1条答案
按热度按时间bvuwiixz1#
这就是众所周知的Hibernate反直觉行为。
首先,如果刷新模式设置为
AUTO
,em.flush()
调用可能是多余的(在这种情况下,Hibernate会在执行更新/删除查询之前自动将persistence context
(会话级缓存)与底层数据库同步)。删除和连续选择案例:
delete
,然后发出select
,因为select
不再显示已删除的记录,所以您在结果集中看不到已删除的记录,但是如果您调用findById
,则可能会找到已删除的记录。更新和后续选择案例:
update
,然后select
。Hibernate看到存储在数据库中的记录和存储在persistence context
中的记录,并且它假设**persistence context
是真实数据的来源**,这就是您看到“陈旧”数据的原因。有以下选项可以缓解这种违反直觉的行为:
1.不执行直接更新,而是使用“慢”
find/save
APIdetach
或refresh
在直接更新之后的陈旧实体,em.clear()
也可能有帮助,但是它完全清除了persistence context
,这可能是不希望的