2012-09-01 11 views
5

Ho un progetto molto utilizzato su cui sto lavorando attualmente in fase di aggiornamento. Esistono diversi luoghi in cui è possibile installare questo progetto e in futuro non è sicuro quale versione venga utilizzata dove e in quale versione si possa essere aggiornati in futuro. In questo momento sono tutti uguali, però.Creazione query query HSQL dalla classe

Il mio problema deriva dal fatto che potrebbero esserci molte modifiche alle classi di entità di ibernazione, e deve essere facile da aggiornare a una versione più recente senza problemi e senza perdita di contenuto del database. Basta sostituire WAR e avviare e dovrebbe migrare se stesso.

A mia conoscenza, Hibernate non modifica le tabelle a meno che non sia hibernate.hbm2ddl.auto = creare, ma che in realtà elimina tutti i dati?

In questo momento, quando il contesto Spring è completamente caricato, esegue un bean che migrerà il database alla versione corrente passando da tutte le modifiche da versionX a versionY (quale versione precedentemente era salvata nel database) e modifica manualmente la tabella.

Non è più problemi a fare un paio di hard-coded ALTER TABLE per aggiungere alcune colonne, ma quando si tratta di aggiungere nuove tabelle complete, si sente stupido dover scrivere tutto ciò che ...

Quindi il mio question (s) è questo:

  • esiste un modo per inviare una classe di entità e di un dialetto di Hibernate codice da qualche parte, e tornare una query SQL valida per la creazione di un tavolo?

  • E ancora meglio, in qualche modo creare una stringa SQL per aggiungere una colonna a una tabella, dialetto-sicuro?

Spero che questa non è una domanda stupida, e non ho perso una cosa ovvia quando si tratta di Hibernate ...

risposta

2

Non credo che sarete in grado di automatizzare completamente questo. Hibernate ha lo strumento hbm2ddl (disponibile come task ant o un plugin maven) per generare le istruzioni DDL richieste dalla configurazione di ibernazione per creare un database vuoto ma non sono a conoscenza di alcuno strumento che possa fare un "diff" automatico tra due versioni. In ogni caso, probabilmente stai meglio facendo la diff attentamente a mano, poiché solo tu conosci il tuo modello di oggetto abbastanza bene da essere in grado di scegliere i valori predefiniti corretti per le nuove proprietà di entità esistenti ecc.

Una volta elaborate le differenze, è possibile utilizzare uno strumento come liquibase per gestirle e gestire effettivamente l'applicazione degli aggiornamenti a un database all'avvio dell'applicazione.

+1

Ok, ho deciso che questa sarebbe la risposta migliore. Ho ancora delle riserve su Liquibase come dipendenza o sulla mia Spring + Hibernate + Annotations, ma ha fatto un ottimo lavoro creando query SQL hardcoded che posso usare per la mia soluzione personalizzata. Grazie. – Stmated

+1

Controlla questa risposta da Dipesh: http://stackoverflow.com/a/12259980/433789 – sdouglass

+1

Lasciare che Hibernate faccia il proprio aggiornamento automatico funzioni bene in casi semplici come l'aggiunta di nuove colonne nullable, ma non può far fronte a più complessi migrazioni come la ridenominazione o la rimozione di colonne, la modifica dei tipi, ecc. Immaginate una situazione in cui state aggiungendo una nuova colonna il cui valore deve essere calcolato in base ai valori nelle colonne esistenti (piuttosto che avere un default statico che funzioni per tutte le righe esistenti). –

2

Forse si dovrebbe provare un approccio diverso. Invece di generare uno schema all'aggiornamento del runtime, creane uno "a mano" (potrebbe basarsi però su uno script generato in ibernazione).

Archiviare un numero di versione nel database e creare uno script di aggiornamento per ogni versione successiva. L'unica cosa che devi fare ora è determinare in quale versione il database è attualmente e in modo sequenziale eseguire gli script di aggiornamento necessari per portarlo alla versione corrente.

Per renderlo più robusto è possibile eseguire un test di unità/integrazione che esegue ogni possibile aggiornamento del database e controlla l'integrità del database risultante.

Ho usato questo metodo per un'applicazione che costruisco e funziona perfettamente. Un altro esempio di implementazione di questo modello è Android. Hanno un metodo di aggiornamento sul loro API

http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#onUpgrade(android.database.sqlite.SQLiteDatabase, int, int)

+1

indovino mi prenderò questo come la risposta accettata. Con rammarico mi sembra strano dare il premio in quanto non è davvero una risposta alla mia domanda; ed è la soluzione a cui stavo pensando di ricorrere se la mia domanda fosse effettivamente ritenuta impossibile. Ma immagino che sia stato l'incontro più vicino alle mie idee di non portare ulteriori dipendenze e simili. Grazie – Stmated

+1

Seriamente, dovresti dare un'occhiata a Liquibase e in particolare il suo [supporto per l'ibernazione] (http://liquibase.org/manual/hibernate) ... –

+1

Ho fatto; anche se ho avuto alcune riserve contro di esso durante la lettura della documentazione. Potrebbe essere che non ho letto abbastanza a fondo, e non capire come mescolare bene con il mio ambiente. Potrebbe tornare con un'accettazione rivista, se le cose cambiano. – Stmated

4

Hai provato

hibernate.hbm2ddl.auto=update 

mantiene tutto il database con i dati e accoda solo colonne e tabelle modificate in entità.

+1

Questo è quello che uso, funziona alla grande. – sdouglass

2

Non utilizzare il ddl di Hibernate. Getta via i tuoi dati se vuoi migrare. Ti suggerisco di dare un'occhiata a Liquibase. Liquibase è un controllo di versione del database. Funziona usando i changeset. Ogni changeset può essere creato manualmente oppure puoi lasciare che Liquibase legga la tua configurazione di Hibernate e generi un changeset.

Liquibase può essere avviato tramite molla e quindi dovrebbe andare bene in con il vostro progetto ;-)

Problemi correlati