6

对 - 我想从数据库中删除(例如)1,000,000 条记录。这需要很长时间 -> 事务超时并失败。所以 - 我分批删除它们,说每笔交易有 25000 条记录。在 MySQL 上使用 limit 子句或在 Oracle 上使用 ROWNUM。太好了,这很有效。

我想以独立于数据库的方式执行此操作。并且来自使用 JPA/Hibernate 的现有 Java 代码库。

运气不好。JPA Query.setMaxResults 和 setFirstResult 对写入“查询”(例如删除)没有影响。我会说,将许多实体选择到内存中以单独删除它们是非常缓慢和愚蠢的。

所以我使用本机查询并管理应用程序代码中的“限制”子句。将此子句封装在 orm.xml 中会很好,但是……“Hibernate Annotations 3.2 不支持使用本机查询进行批量更新/删除。” - http://opensource.atlassian.com/projects/hibernate/browse/ANN-469

我想这是一个普遍的问题。有人有更好的数据库独立解决方案吗?

4

4 回答 4

5

我讨厌给出一个非建设性的答案,但 ORM 并不真正意味着对数据库进行批量操作。因此,看起来您的本机查询可能是这些操作的最佳选择。

您还应该确保更新您的 ORM 以反映数据库的新状态,否则您可能会发生一些奇怪的事情。

ORM 是将对象映射到数据库的好工具,但它们通常不是通用的数据库接口。

于 2009-02-09T12:51:52.950 回答
0

我相信您可以使用 HQL (JPA QL) 直接 DML 操作,它将绕过持久性上下文和缓存,并直接执行(生成的 SQL)语句:

Query q = session.createQuery("delete YourEntity ye where ye.something like :param");
q.setParameter("param", "anything");
int deletedEntities = q.executeUpdate();
于 2009-02-09T22:05:55.130 回答
0

查询限制是数据库特定的功能,没有 SQL 标准(我同意应该有)。

适用于大多数数据库的解决方案是使用视图将多个表组合为一个。每个表都包含数据的一个子集(比如一天)。这允许您一次删除整个子集。也就是说,许多数据库在此类视图上运行 UPDATE 和 INSERT 时存在问题。

您通常可以通过为 INSERT/UPDATE(指向单个表;“当前”表)和用于搜索的分组视图创建视图或别名来解决此问题。

一些数据库还提供基本相同的分区,除了您可以定义一个列,该列指定一行应该进入哪个基础表(在 INSERT 上)。当您需要删除一个子集时,您可以删除/截断其中一个基础表。

于 2009-02-09T12:46:06.550 回答
-2

q.setMaxResults(int)

...索尼

于 2010-11-19T09:16:22.870 回答