通过Java ORM批量删除/清除记录

时间:2009-02-09 12:28:40

标签: java batch-file jpa purge

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

我想以独立于数据库的方式这样做。 并且来自使用JPA / Hibernate的现有Java代码库。

运气不好。 JPA Query.setMaxResults和setFirstResult没有 写'查询'的效果(例如删除)。选择许多实体 在内存中单独删除它们是非常缓慢和愚蠢的我会说。

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

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

4 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:0)

查询限制是一种特定于数据库的功能,并且没有SQL标准(我同意应该这样)。

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

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

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

答案 2 :(得分: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();

答案 3 :(得分:-1)

q.setMaxResults(int)

...索尼