让 JPA 了解数据库更改
我有两个实体,交易和条目。交易有一些自己的数据和一个或多个条目的列表,其中包含借方和贷方金额。在应用程序的一部分中,我需要删除几乎所有这些内容,并发现 JPQL 在这种情况下是最简单且最快的。
我执行这段代码:
entityManager.createQuery(
"DELETE FROM Entry e WHERE e IN (:entries)").
setParameter("entries", new ArrayList<Entry>(
entriesToRemove)).executeUpdate();
entityManager.createQuery(
"DELETE FROM Transaction e WHERE e IN (:transactions)").
setParameter("transactions", new ArrayList<Transaction>(
transactions)).executeUpdate();
问题出在代码的后面,仍然在同一个事务中(这次是执行事务)我需要遍历某些事务上存在的所有条目,EntityManager 仍然为我提供了我最近删除的事务。
我怀疑应该有一种方法来处理此事件,在我的示例中,我只执行两个删除 JPQL,但我也可以调用外部服务或影响数据库之外的其他内容。无论如何,我需要确保 EntityManager 的缓存仍然有效,因为它现在仍然包含已删除的对象。
我尝试过使用entityManager.flush();这些删除后没有成功。因为我使用executeUpdate();删除会立即刷新到底层数据库,所以我并没有真正期望它有帮助。
感谢所有的指点、提示和答案。
I have two Entities, Transaction and Entry. Transaction has some own data and a list of one or several Entries which consists of a debit and a credit amount. In one part of the application I need to remove almost all of these and found that JPQL is easiest and fastest in this instance.
I execute this code:
entityManager.createQuery(
"DELETE FROM Entry e WHERE e IN (:entries)").
setParameter("entries", new ArrayList<Entry>(
entriesToRemove)).executeUpdate();
entityManager.createQuery(
"DELETE FROM Transaction e WHERE e IN (:transactions)").
setParameter("transactions", new ArrayList<Transaction>(
transactions)).executeUpdate();
The problem is later in the code, still in the same transaction (execution transaction this time) I need to traverse all the entries that exists on some transactions, the EntityManager still gives me the transactions that I just recently removed.
I suspect that there should be a way of handling this event, in my example here I just execute two delete JPQLs but I could also have called an external service or something else outside that affected the database. In any case I need to make sure that the EntityManager's cache is still valid, because as it is now it still contains the deleted objects.
I have tried with entityManager.flush(); after these deletes to no success. Since I use executeUpdate(); the deletes are flushed immediately to the underlaying database so I didn't really expect it to help.
Appreciate any and all pointers, hints and answers.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用 < 清除整个缓存
EntityManager
接口中的 code>clear() 方法或者,如果您知道所有交易都属于某个帐户,则可以调用
刷新(对象实体)
位于Account
对象的EntityManager
中。You can clear the whole cache, using the
clear()
method fromEntityManager
interfaceOr, if you know that all transactions belongs to a certain account, you can call
refresh(Object entity)
in theEntityManager
for theAccount
object.冲洗模式
AUTO
是默认行为。您在事务中所做的任何更新都会被刷新,以便您的查询将获取这些更改。COMMIT
表示仅在事务提交时刷新更改,而不是在任何查询之前刷新。如果您使用 FlushModeType.COMMIT,则可能会出现问题,因为更改仅反映在事务提交上您正在同一事务中执行两个查询。使用
FlushModeType.AUTO
它应该可以正常工作它是默认的,因此无需明确提及。如果问题仍然存在,那么您可以尝试在第一次查询后提交事务。
Flush Mode
AUTO
is the default behavior. Any updates you've made within your transaction are flushed so that your query will pick up these changes.COMMIT
means that changes are flushed only when the transaction commits, not before any query.Probably if you are using
FlushModeType.COMMIT
, then the problem can arise as the changes are reflected on transaction commit only & you are executing two queries within same transaction. WithFlushModeType.AUTO
it should work fine & its default so no need to mention it explicitly.If still problem exists, then you can try committing the transaction after first query.
首先,你确定批量删除语句是必要的吗?也就是说,如果没有它,您将跨越一些不良的性能阈值。如果您不需要它,则可以使用
session.delete(e)
。否则,如果您使用 hibernate,如问题中的标签所示,您可以使用
session.evict(e)
手动从会话中删除实体。您可以使用推荐的代码 此处。希望有帮助。
First of all, are you sure that the bulk delete statement is necessary? i.e. you will cross some undesirable performance threshold if you don't have it. If you don't need it then you can use
session.delete(e)
.Otherwise, if you're using hibernate, as the tag in your question indicates, you can use
session.evict(e)
to remove entities from the session manually. You can get to the hibernate session by using the code recommended here.Hope that helps.