2009-02-09 8 views
5

Droit - Je souhaite supprimer (par exemple) 1 000 000 enregistrements d'une base de données. Cela prend beaucoup de temps -> la transaction expire et échoue. Donc, je les supprime par lots, disons 25000 enregistrements par transaction. Utilisation de la clause limit sur MySQL ou ROWNUM sur Oracle. Super ça marche.Suppression par lots/purge d'enregistrements via Java ORM

Je veux faire cela dans une base de données indépendante. Et à partir d'une base de code Java existante qui utilise JPA/Hibernate.

De la chance. JPA Query.setMaxResults et setFirstResult n'ont pas d'effet pour l'écriture des 'requêtes' (suppression par exemple). Sélectionnant de nombreuses entités en mémoire pour les supprimer individuellement est très lent et bête je dirais. Donc, j'utilise une requête native et gère la clause 'limit' dans le code de l'application. Ce serait bien d'encapsuler cette clause dans orm.xml mais ... "Hibernate Annotations 3.2 ne supporte pas les mises à jour/suppressions groupées en utilisant des requêtes natives." - http://opensource.atlassian.com/projects/hibernate/browse/ANN-469.

J'imagine que c'est un problème commun. Quelqu'un at-il une meilleure solution indépendante de base de données?

Répondre

0

Limites sur les requêtes est une fonctionnalité spécifique à la base de données et il n'y a pas de norme SQL (je suis d'accord, il devrait y avoir).

Une solution qui fonctionne avec la plupart des bases de données utilise une vue pour regrouper plusieurs tables en une seule. Chaque table contient un sous-ensemble de données (disons un jour). Cela vous permet de supprimer tout un sous-ensemble à la fois. Cela dit, de nombreuses bases de données ont des problèmes avec l'exécution de UPDATE et INSERT sur une telle vue.

Vous pouvez généralement contourner ce problème en créant une vue ou un alias pour INSERT/UPDATE (qui pointe vers une seule table, la table "actuelle") et une vue de regroupement pour la recherche.

Certaines bases de données offrent également des partitions, ce qui est fondamentalement la même chose, sauf que vous pouvez définir une colonne qui spécifie dans quelle table sous-jacente une ligne doit aller (sur INSERT). Lorsque vous devez supprimer un sous-ensemble, vous pouvez supprimer/tronquer l'une des tables sous-jacentes.

5

Je déteste donner une réponse non constructive mais un ORM n'est pas vraiment destiné à faire des opérations en masse sur la base de données. Il semble donc que votre requête native soit probablement la meilleure solution pour ces opérations.

Vous devez également vous assurer que votre ORM est mis à jour pour refléter le nouvel état de la base de données, sinon vous risquez d'avoir un peu d'étrangeté. Les ORM sont d'excellents outils pour mapper des objets aux bases de données, mais ils ne sont généralement pas des interfaces de base de données génériques.

0

Je crois que vous pouvez utiliser HQL (JPA QL) opérations DML directes qui contournent le contexte de persistance et de cache, et exécuter les instructions (résultant SQL) directement:

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

Je pense que la question-asker est déjà en train de le faire, mais en trouvant que la suppression est si lente, elle expire. –

0

q.setMaxResults(int)

.. .sony

+0

L'OP a déjà indiqué avoir essayé cela sans succès: «Pas de chance. Requête JPA.setMaxResults et setFirstResult n'ont aucun effet pour écrire des 'requêtes' ... ' – Mac

Questions connexes