2009-02-09 20 views
5

Rechts - Ich möchte (z. B.) 1.000.000 Datensätze aus einer Datenbank löschen. Das dauert lange -> die Transaktion läuft ab und schlägt fehl. Also - ich lösche sie in Chargen sagen 25000 Datensätze pro Transaktion. Verwenden der Limit-Klausel für MySQL oder ROWNUM für Oracle. Großartig funktioniert das.Löschen/Löschen von Datensätzen über Java ORM

Ich möchte dies in einer datenbankunabhängigen Art und Weise tun. Und von einer vorhandenen Java-Codebasis, die JPA/Hibernate verwendet.

Pech gehabt. JPA Query.setMaxResults und setFirstResult haben keinen -Effekt zum Schreiben von Abfragen (z. B. delete). Das Auswählen vieler Entitäten in den Speicher, um sie einzeln zu löschen, ist sehr langsam und dumm, würde ich sagen.

Also verwende ich eine native Abfrage und verwalten Sie die 'Limit' -Klausel im Anwendungscode. Es wäre nett, diese Klausel in orm.xml zu kapseln, aber ... "Hibernate Annotations 3.2 unterstützt keine Bulk-Aktualisierung/löscht mit nativen Abfragen." - http://opensource.atlassian.com/projects/hibernate/browse/ANN-469.

Ich könnte mir vorstellen, dass dies ein häufiges Problem ist. Hat jemand eine bessere datenbankunabhängige Lösung?

Antwort

0

Limits auf Abfragen ist eine datenbankspezifische Funktion und es gibt keinen SQL-Standard (ich stimme zu, dass es sein sollte).

Eine Lösung, die mit den meisten Datenbanken funktioniert, verwendet eine Ansicht, um mehrere Tabellen zu einer zu gruppieren. Jede Tabelle enthält eine Teilmenge der Daten (zB einen Tag). Auf diese Weise können Sie eine ganze Untergruppe gleichzeitig löschen. Das heißt, viele Datenbanken haben Probleme mit dem Ausführen von UPDATE und INSERT für eine solche Ansicht.

Sie können dies normalerweise umgehen, indem Sie eine Ansicht oder einen Alias ​​für INSERT/UPDATE (der auf eine einzige Tabelle verweist; die "aktuelle") und eine Gruppierungsansicht für die Suche erstellen.

Einige Datenbanken bieten auch Partitionen, die im Grunde die gleiche Sache ist, außer dass Sie eine Spalte definieren können, die angibt, in welcher zugrunde liegenden Tabelle eine Zeile gehen soll (auf INSERT). Wenn Sie eine Teilmenge löschen müssen, können Sie eine der zugrunde liegenden Tabellen löschen.

5

Ich hasse es, eine nicht konstruktive Antwort zu geben, aber ein ORM ist nicht wirklich für Massenoperationen in der Datenbank gedacht. Es sieht also so aus, als ob Ihre native Abfrage wahrscheinlich die beste Option für diese Operationen ist.

Sie sollten auch sicherstellen, dass Ihr ORM aktualisiert wird, um den neuen Zustand der Datenbank widerzuspiegeln, sonst können Sie einige seltsame Dinge passieren.

ORMs sind großartige Werkzeuge zum Zuordnen von Objekten zu Datenbanken, aber sie sind im Allgemeinen keine generischen Datenbankschnittstellen.

0

Ich glaube, Sie HQL (JPA QL) direkte DML-Operationen verwenden können, die die Persistenz Kontext und Cache umgehen, und führen Sie die (resultierende SQL) Anweisungen direkt:

Query q = session.createQuery("delete YourEntity ye where ye.something like :param"); 
q.setParameter("param", "anything"); 
int deletedEntities = q.executeUpdate(); 
+0

Ich denke, der Fragesteller ist bereits dabei, aber zu finden, dass das Löschen ist so langsam es Timeout. –

0

q.setMaxResults(int)

.. .sony

+0

Das OP zeigte bereits an, dass sie dies ohne Erfolg versuchten: "Pech gehabt. JPA-AbfragesetMaxResults und setFirstResult haben keine Auswirkung auf 'Abfragen' schreiben ' – Mac

Verwandte Themen