Java, che si occupa di classi annotate XML e JPA
Uso xjc per compilare file XSD in classi Java e desidero modificarli / estenderli per renderli persistenti tramite JPA.
Non riesco a capire quale sia il miglior "accoppiamento?" sarebbe e come organizzarlo, se modifico le classi compilate xjc per essere persistenti, perderei la capacità di ricompilare l'XSD se ci sono modifiche.
Anche se non avessi bisogno di ricompilare, in alcuni casi, non sarei ancora in grado di serializzare / deserializzare i dati raccolti prima della modifica dello schema.
Non voglio "disaccoppiare" completamente, poiché voglio mantenere la capacità di Persistere l'oggetto XML importato con poche righe di codice (senza dover scrivere una sorta di "convertitore" per ogni entità XML).
Qualcuno ha dovuto affrontare lo stesso problema? Come sei riuscito a risolverlo.
Risposte
Penso che il problema più grande che stai affrontando qui sia che per le classi che devono essere "visibili" a qualcosa al di fuori del tuo codice, è importante avere una fonte di verità per ciò che conta come dati validi. Altrimenti ti ritroverai con infinite ore di lavoro spesi per sincronizzare le molte definizioni e le loro implementazioni. O le specifiche non sono sincronizzate (o diventano fuori sincronizzazione nel tempo) oppure i convertitori non sono compatibili con le ultime versioni delle specifiche ecc. Nel tuo caso, le classi sono entrambe visibili a
- qualunque cosa stia producendo / consumando i dati XML che vengono convertiti in / dalle classi Java
- e al database dietro JPA che impone i propri requisiti di tipo e integrità dei dati sui dati.
Il tuo approccio rischia di violare questo importante principio se non stai attento. O l'XSD è la fonte della verità o lo sono le definizioni JPA o qualcos'altro lo è completamente, ma secondo questo principio n-1 di n definizioni devono dipendere dall'n-esimo.
Allora qual è la soluzione? Come sempre, dipende fortemente da cosa vuoi fare.
Forse non ci sono così tante classi e forse non cambiano mai o cambiano solo molto poco e molto raramente. In tal caso potresti decidere di accettare il costo di avere due fonti di verità.
Come lo faresti? Come hai già detto, è molto fragile modificare il codice generato automaticamente. È anche inutilmente faticoso avere classi separate solo per le annotazioni JPA, perché ciò richiederebbe un sacco di codice boilerplate per i convertitori. Fortunatamente la specifica JPA consente la configurazione XML delle mappature ORM invece della solita configurazione basata sull'annotazione. Dai un'occhiata al file orm.xml . Con esso puoi definire una classe come un'entità JPA senza alcuna modifica al suo codice sorgente.
Se il tuo XSD è abbastanza semplice, potrebbe essere possibile generare la struttura del database direttamente dall'XSD. Ci sono strumenti per questo. Questo però non ti dà la mappatura ORM. Ma se l'XSD è abbastanza semplice, potrebbe anche essere possibile generare automaticamente il file orm.xml dall'XSD. Ciò ristabilirebbe l'XSD come unica fonte di verità.
Se 1. e 2. non sono opzioni per te, perché la tua struttura dati è troppo complicata, forse è possibile avere una terza specifica che può servire come fonte di verità per entrambi ed è in grado di generare sia gli XSD che il Definizioni JPA in qualche forma. In linea di principio potresti avere un file XML aumentato che contiene sia le definizioni XSD che ORM, nonché un XSLT che estrae le due metà. (Ovviamente potresti usare qualsiasi altro (meta) linguaggio invece di XML per le specifiche principali, se lo desideri) Quindi il tuo processo di compilazione avrebbe bisogno di un altro passo avanti. Ma attenzione: a seconda delle complicazioni nella struttura dei dati, questo può essere incredibilmente difficile da eseguire il debug / modificare in caso di necessità.
Potresti fare in modo che il codice Java sia la fonte della verità ed esportare invece l'XSD. Ovviamente, potresti usare l'esportazione JSON invece di XML molto più facilmente. Non penso sia molto probabile, perché gli XSD di solito sono dati da specifiche esterne e non generati per capriccio, ma ehi, forse sei l'eccezione alla regola?
In ogni caso, devi essere consapevole che i punti più fini di XML e ORM come JPA non sono necessariamente compatibili tra loro e il tuo desiderio di una completa unificazione potrebbe essere condannato fin dall'inizio. Potrebbe semplicemente accadere che alcuni aspetti dei tuoi dati XML non possano essere convertiti in database land e viceversa. Ad esempio: un concetto di transazione non esiste nella terra XML. JPA ha una conoscenza (limitata) delle procedure memorizzate, dei trigger di database e di altre funzionalità (semi) avanzate dei database. Non sono a conoscenza di nulla in XML land che sia in qualche modo simile a quello. E viceversa, non esiste un cugino stretto di XSLT nel database land.
Inoltre: JPA può essere molto inefficiente se gestisci grandi quantità di dati; a volte scrive orrendi SQL se la configurazione non è ottimizzata; ha un comportamento non completamente diretto con le transazioni, il caricamento lento ecc. È ottimo per astrarre i dettagli dei database, ma come con qualsiasi astrazione del genere può costarti se non sai cosa sei facendo. Potrebbe essere semplicemente impossibile ottenere tutti i punti più fini corretti quando si lascia tutto questo a uno strumento automatizzato.
Dovresti tenerlo a mente in modo da poter fornire una buona interfaccia sia per l'aggiunta di funzionalità mancanti su entrambe le estremità sia per la messa a punto delle mappature.