Пакетное удаление / очистка записей через Java ORM - PullRequest
5 голосов
/ 09 февраля 2009

Справа - я хочу удалить (например) 1 000 000 записей из базы данных. Это занимает много времени -> транзакция истекает и завершается неудачно. Итак - я удаляю их партиями, скажем, 25000 записей за транзакцию. Использование предложения limit в MySQL или ROWNUM в Oracle. Отлично, это работает.

Я хочу сделать это независимо от базы данных. И из существующей базы кода Java, которая использует JPA / Hibernate.

Не повезло. JPA Query.setMaxResults и setFirstResult не имеют эффект для записи «запросов» (например, удалить). Выбор многих объектов в память, чтобы удалить их по отдельности, очень медленно и глупо, я бы сказал.

Поэтому я использую собственный запрос и управляю предложением limit в коде приложения. Было бы неплохо заключить этот пункт в orm.xml, но ... «Hibernate Annotations 3.2 не поддерживает массовое обновление / удаление с использованием собственных запросов». - http://opensource.atlassian.com/projects/hibernate/browse/ANN-469.

Полагаю, это обычная проблема. Кто-нибудь получил лучшее решение, независимое от базы данных?

Ответы [ 4 ]

5 голосов
/ 09 февраля 2009

Я не хочу давать неконструктивный ответ, но ORM на самом деле не предназначен для выполнения массовых операций с базой данных. Похоже, что ваш родной запрос, вероятно, является лучшим выбором для этих операций.

Вы также должны убедиться, что ваш ORM обновлен, чтобы отразить новое состояние базы данных, иначе вы можете столкнуться со странностями.

ORM являются отличными инструментами для сопоставления объектов с базами данных, но обычно они не являются общими интерфейсами баз данных.

0 голосов
/ 19 ноября 2010

q.setMaxResults(int)

... сони

0 голосов
/ 10 февраля 2009

Я полагаю, что вы можете использовать прямые операции DML HQL (JPA QL), которые будут обходить контекст персистентности и кеш, а также напрямую выполнять (результирующий SQL) оператор:

Query q = session.createQuery("delete YourEntity ye where ye.something like :param");
q.setParameter("param", "anything");
int deletedEntities = q.executeUpdate();
0 голосов
/ 09 февраля 2009

Ограничения на запросы - это особенность базы данных, и нет стандарта SQL (я согласен, что так и должно быть).

Решение, которое работает с большинством баз данных, использует представление для группировки нескольких таблиц в одну. Каждая таблица содержит подмножество данных (скажем, один день). Это позволяет вам отбросить целое подмножество одновременно. Тем не менее, многие базы данных имеют проблемы с запуском UPDATE и INSERT в таком представлении.

Обычно это можно обойти, создав представление или псевдоним для INSERT / UPDATE (который указывает на одну таблицу; «текущую») и групповое представление для поиска.

Некоторые базы данных также предлагают разделы, что в основном то же самое, за исключением того, что вы можете определить столбец, в котором указывается, в какой базовой таблице должна идти строка (на INSERT). Когда вам нужно удалить подмножество, вы можете удалить / усечь одну из базовых таблиц.

...