2009-02-09 15 views
5

Right: desidero eliminare (ad esempio) 1.000.000 record da un database. Questo richiede molto tempo -> la transazione è scaduta e fallisce. Quindi - li cancello in batch dicono 25000 record per transazione. Utilizzo della clausola limite su MySQL o ROWNUM su Oracle. Ottimo questo funziona.Eliminazione/eliminazione batch di record tramite Java ORM

Voglio farlo in un modo indipendente dal database. E da una base di codice Java esistente che utilizza JPA/Hibernate.

Sfortunato. JPA Query.setMaxResults e setFirstResult non hanno effetto per scrivere 'query' (ad es. Cancellare). Selezionare molte entità in memoria per eliminarle singolarmente è molto lento e stupido direi.

Quindi uso una query nativa e gestisco la clausola 'limite' nel codice dell'applicazione. Sarebbe bello incapsulare questa clausola in orm.xml ma ... "Hibernate Annotations 3.2 non supporta l'aggiornamento/eliminazione di massa utilizzando query native." - http://opensource.atlassian.com/projects/hibernate/browse/ANN-469.

Immagino che questo sia un problema comune. Qualcuno ha una migliore soluzione indipendente dal database?

risposta

0

I limiti sulle query sono una funzionalità specifica del database e non esiste uno standard SQL (sono d'accordo che ci dovrebbe essere).

Una soluzione che funziona con la maggior parte dei database utilizza una vista per raggruppare più tabelle in una sola. Ogni tabella contiene un sottoinsieme dei dati (ad esempio un giorno). Ciò ti consente di rilasciare un intero sottoinsieme in una sola volta. Detto questo, molti database hanno problemi con l'esecuzione di UPDATE e INSERT su tale visualizzazione.

In genere è possibile aggirare questo creando una vista o un alias per INSERT/UPDATE (che punta a una singola tabella, quella "corrente") e una vista di raggruppamento per la ricerca.

Alcuni database offrono anche partizioni che sono fondamentalmente la stessa cosa, tranne che è possibile definire una colonna che specifica in quale tabella sottostante deve andare una riga (su INSERT). Quando è necessario eliminare un sottoinsieme, è possibile eliminare/troncare una delle tabelle sottostanti.

5

Detesto dare una risposta non costruttiva, ma un ORM non è realmente pensato per eseguire operazioni di massa sul database. Quindi sembra che la tua query nativa sia probabilmente la migliore scommessa per queste operazioni.

È inoltre necessario assicurarsi che il proprio ORM sia aggiornato in modo da riflettere il nuovo stato del database, altrimenti si potrebbero verificare stranezze.

Gli ORM sono ottimi strumenti per la mappatura di oggetti nei database, ma non sono generalmente interfacce di database generiche.

0

Credo che si può utilizzare HQL (JPA) QL operazioni DML diretti che bypassare il contesto di persistenza e la cache, ed eseguire direttamente le dichiarazioni (risultante SQL):

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

Penso che chi fa la domanda lo stia già facendo, ma trovando che l'eliminazione sia così lenta, scade. –

0

q.setMaxResults(int)

.. .sony

+0

L'OP ha già indicato che ci hanno provato senza successo: "sfortuna. Domanda JPA.setMaxResults e setFirstResult non hanno effetto per scrivere 'query' ... ' – Mac