Come l'ibernazione ha quasi rovinato la mia carriera
Pubblicato: 2022-03-11Immagina di essere uno sviluppatore Java e di essere in procinto di iniziare il tuo prossimo grande progetto. Devi prendere le decisioni fondamentali che rimarranno con te per il resto del progetto. Vuoi scegliere la migliore astrazione orientata agli oggetti del tuo modello di dati flessibile perché non vuoi gestire un semplice SQL. Vuoi supportare tutti i tipi di dati e, idealmente, supportare tutti i tipi di database.
La risposta ovvia è usare semplicemente Hibernate , giusto? Il 90% degli sviluppatori Java sarebbe d'accordo con te, ma è la decisione giusta?
Diamo un'occhiata a cosa può andare storto se usi ciecamente Hibernate solo perché è lo standard accettato.
Si consideri Monica, uno sviluppatore Java. Monica è stata recentemente promossa al ruolo di architetto ed è ora responsabile della progettazione dello stack tecnologico per un nuovo prodotto presso la sua azienda. Sa che nel mondo Java esiste un solo buon strumento per gestire la comunicazione del database: Hibernate . Hibernate è uno standard JPA ben noto e supportato. Tuttavia, è sempre una buona idea controllare alcune cose prima di iniziare un progetto. Fortunatamente, il suo collega, Ben, conosce la persona giusta.
L'ibernazione suona come un proiettile d'argento
Ben - Ciao Monica, vorrei presentarti John. È un esperto di Hibernate e ti aiuterà.
Monica - Ehi John, felice che tu abbia trovato del tempo per me. Quindi, stiamo costruendo la nostra prossima grande cosa, lo sai. Stiamo progettando di diventare il prossimo Facebook o Google. Giorni occupati. Sarà enorme. Assolutamente fantastico! Tutti sono così eccitati! Sono stato promosso al ruolo di architetto, quindi ora devo selezionare lo stack che useremo. L'unica parte che manca è la tenacia...
Giovanni - Iberna !
Monica - Sì! Esattamente! Proprio quello che stavo pensando! Sembra una partita perfetta e il vero affare per noi. Una vera soluzione aziendale per un vero problema aziendale, comprovata dal mercato e con una lunga storia. Ho sentito tante esperienze positive con esso. Tuttavia, ho un problema con uno dei nostri compagni di squadra; è totalmente contrario. Sa molto sui database e ha paura di aggiungere un altro livello tra la nostra applicazione e il database. È super intelligente e ho bisogno di argomenti davvero validi per convincerlo che questa è una buona decisione. Puoi aiutarmi con quello?
Giovanni - Certo! sarò felice di farlo. L'ibernazione è, infatti, uno strumento eccezionale. È ampiamente utilizzato nelle grandi soluzioni aziendali, come le banche. Non puoi sbagliare. Pensa alla persistenza: scegli Ibernazione . Se stai scrivendo in Java, questa è assolutamente la scelta giusta, inoltre hai porte per altre lingue. Guarda quante descrizioni di lavoro lo richiedono!
Monica - Sono assolutamente d'accordo! Ho le stesse sensazioni al riguardo. In un progetto precedente, stavamo utilizzando principalmente SQL tramite il normale vecchio JDBC. Ridicolo! Lo so! Ma ecco il punto: abbiamo ragazzi SQL davvero intelligenti nel team e quando hanno visto SQL generato da Hibernate si sono innervositi. Sembrava brutto e illeggibile; sarà un problema in futuro?
Giovanni - Guarda. I ragazzi del DBA hanno una prospettiva diversa. Hanno paura di Hibernate perché sembra sostituire il loro ruolo nel progetto. Inoltre, i database dispongono di ottimizzatori di query integrati, quindi non devi preoccuparti di come appariranno effettivamente quelle query. Il database lo ottimizzerà per te. Si tratta di uno sviluppo rapido, cosa che SQL non può fare.
Monica - Davvero?! Non hai più a che fare con SQL? Sorprendente! L'ultima volta che un DBA ha trascorso settimane cercando di ottimizzare alcune query. Settimane! Oh, mi sento così imbarazzato a dirtelo, ma lo sapevi che stavamo usando... stored procedure (ridendo). Oh, era un tale casino. Riesci a credere che il progetto lo stia ancora utilizzando? Mi dispiace così tanto per le persone là fuori. Devono ancora scrivere questo codice noioso più e più volte. Mi chiedo se è ancora un progetto Java o SQL?
John - Questa è esattamente la differenza tra un approccio orientato agli oggetti e quello relazionale. È una cosiddetta discrepanza di impedenza orientata agli oggetti. L'ibernazione può colmare questa lacuna. Gli sviluppatori possono concentrarsi sulla creazione di logiche di business. Le funzionalità push rendono felici le parti interessate e l'intero management. Fai le cose che contano di più: Affari! Un sacco di codice standard scomparirà e avrai una connessione magica, invisibile, ma affidabile tra la logica e i dati.
Monica - Collaborazione reciproca. Piena sinergia. Come se il database facesse parte della lingua fin dall'inizio. Sono così felice di poter essere un leader di questo salto di fede tecnologico. È come la velocità di curvatura nel viaggio del software.
Giovanni - Già! Ce l'hai!
Monica - Oh Dio, sono così eccitata! Grazie, Giovanni! Sono pronto!
Dolori crescenti con soluzioni non flessibili
Monica - Hey John, ricordi il progetto di cui abbiamo parlato l'anno scorso?
Giovanni - Certo. Come va?
Monica - Presto andremo alla produzione. Va tutto bene, ma sono emerse alcune domande.
John - Certo, picchiami.
Monica - Bene, non possiamo più generare il nostro schema del database da zero. Qual è il modo migliore per supportare le modifiche allo schema senza perdere dati?
John - Innanzitutto, Hibernate non è concepito per essere utilizzato come strumento di migrazione della produzione. Usa qualcosa come FlywayDB o Liquibase. È abbastanza semplice. Annoti gli script di migrazione, quindi aggiorni il modello di entità insieme ai mapping di Hibernate , in modo che rimanga sincronizzato con la struttura del database effettiva.
Monica - Hmm, ho capito. Nel progetto precedente stavamo usando solo una semplice migrazione SQL.
John - Va bene anche questo. Finché mantieni sincronizzati il modello di entità e lo schema, fallo come preferisci.
Monica - Capisco. C'è un'altra cosa. Siamo sempre alle prese con problemi di recupero pigri/desiderosi. Ad un certo punto, abbiamo deciso di fare tutto con entusiasmo, ma sembra non ottimale, e inoltre, a volte non è possibile accedere ad alcuni campi perché non c'è sessione o qualcosa del genere. È normale?
John : devi saperne di più su Hibernate . La mappatura dal database non è semplice. Fondamentalmente, ci sono diversi modi per farlo. Devi solo scegliere un modo che funzioni per te. Il recupero lento ti dà la possibilità di caricare quegli oggetti su richiesta, ma devi operare all'interno di una sessione attiva.
Monica - Stiamo ancora lottando con quale motore di database utilizzare per la distribuzione finale. Pensavo che Hibernate fosse portatile, ma abbiamo alcune query native che usano la magia di MS SQL e in realtà vorremmo utilizzare MySQL nella produzione.
John - Hibernate ti dà flessibilità fintanto che utilizzi criteri distaccati o HQL; qualsiasi query nativa legherà semplicemente la tua soluzione al database.
Monica - Sembra che allora dobbiamo attenerci a MS SQL. Ultima domanda: il mio compagno di squadra ha detto che non esiste una parola chiave "limite" in HQL. Pensavo stesse scherzando, ma non riuscivo nemmeno a trovarlo. Scusate per la domanda stupida…
John - In effetti, non esiste una parola chiave "limite" in HQL. Puoi controllarlo tramite l'oggetto query poiché è specifico del fornitore di database.
Monica - Sembra strano che tutti gli altri elementi siano in HQL. Non importa. Grazie per il tuo tempo!
Ora stiamo di nuovo hackerando insieme soluzioni in SQL
Monica - John, all'inizio non avremmo avuto a che fare con SQL, ma ora sembra che dobbiamo farlo. I nostri bisogni stanno crescendo e sembra che non ci sia modo di aggirarlo. Sembra sbagliato, ma abbiamo ricominciato a utilizzare SQL su base giornaliera.

John - Beh, non è sbagliato. All'inizio non dovevi concentrarti sul database. Tuttavia, man mano che il progetto cresce, è bene utilizzare SQL e lavorare sull'ottimizzazione delle prestazioni.
Monica - A volte passiamo giorni a cercare errori. Sembra che dobbiamo analizzare l'SQL generato da Hibernate perché non abbiamo idea del perché non funzioni come previsto e stia producendo risultati inaspettati. Abbiamo riscontrato alcuni problemi ben noti nel bug tracker di Hibernate . Inoltre, è difficile scrivere migrazioni corrette mantenendo sincronizzato il modello di entità. È dispendioso in termini di tempo poiché dobbiamo imparare molto sugli interni di Hibernate e prevedere come funzionerà.
John - C'è sempre una curva di apprendimento. Non devi scrivere molto, ma devi sapere come funziona.
Monica - Anche lavorare con set di dati più grandi è fastidioso. Di recente, abbiamo eseguito un'importazione massiccia nel database ed è stata dolorosamente lenta. Poi abbiamo scoperto che dovevamo cancellare la sessione per renderla più veloce. Anche così, è ancora significativamente più lento, quindi abbiamo deciso di riscriverlo come semplici istruzioni SQL. La cosa divertente è che scrivere un semplice SQL era in realtà il modo più veloce per farlo, quindi abbiamo deciso di farlo come ultima opzione.
John - L'importazione non è un processo orientato agli oggetti. Hibernate si concentra sul design orientato agli oggetti. Ricorda che puoi sempre utilizzare le query native.
Monica - Puoi aiutarmi a capire come funziona la cache di Hibernate ? Semplicemente non capisco. Ci sono alcune cache di primo/secondo livello. Che cosa è questa storia?
Giovanni - Certo. È una cosiddetta cache a livello di transazione di dati persistenti. È possibile configurare un cluster o una cache a livello di JVM su base classe per classe e raccolta per raccolta. Puoi anche collegare una cache in cluster. Ma ricorda che le cache non sono a conoscenza di eventuali modifiche apportate all'archivio persistente da un'altra applicazione. Tuttavia, possono essere configurati per eliminare regolarmente i dati memorizzati nella cache scaduti.
Monica - Scusa, penso che sto passando una brutta giornata. Puoi spiegarlo un po' di più?
Giovanni - Certo. Ogni volta che si passa un oggetto per save
, update
, saveOrUpdate
o recuperarlo tramite load
, get
, list
, iterate
o scroll
, quell'oggetto viene aggiunto alla cache interna della sessione. Puoi anche rimuovere l'oggetto e le sue raccolte dalla cache di primo livello.
Monica - Ehm...
John - Inoltre, puoi controllare le modalità della cache. È possibile utilizzare la modalità normal
per leggere e scrivere elementi nella cache di secondo livello. Usa la modalità get
per leggere dal secondo livello ma non puoi riscrivere. Usa put
, che è uguale a get
ma non puoi leggere dal secondo livello. Puoi anche utilizzare la modalità di refresh
, che scriverà al secondo livello, ma non leggerà da esso e ignora la proprietà use minimal puts
, forzando un aggiornamento della cache di secondo livello per tutti gli elementi letti dal database.
Monica - Capisco. Ok. Fammi pensare a questo. Oh, è tardi, devo andare. Grazie per il tuo tempo!
Giovanni - Prego!
Rinunciare all'ibernazione
Monica - John, pensavo che stessimo entrando in una nuova era di sviluppo software. Pensavo stessimo facendo il salto di un anno luce. Ma, dopo quattro anni, sembra che stiamo ancora affrontando tutti gli stessi problemi, solo da un'angolazione diversa. Ho dovuto imparare l'architettura di Hibernate , la configurazione, la registrazione, le strategie di denominazione, i tuplizer, i risolutori di nomi di entità, i generatori di identificatori avanzati, l'ottimizzazione del generatore di identificatori, le sottoclassi di unione, il markup XDoclet, le associazioni bidirezionali con le raccolte indicizzate, le associazioni ternarie, l'idbag, la miscelazione del polimorfismo implicito con altre mappature dell'ereditarietà, replica di oggetti tra due diversi datastore, oggetti distaccati e controllo automatico delle versioni, modalità di rilascio della connessione, interfaccia di sessione stateless, tassonomia della persistenza della raccolta, livelli di cache, recupero pigro o ansioso e molti, molti altri. Anche con tutto quello che so, sembra che abbiamo fallito gravemente. È un fiasco del software! Ultimo fallimento! Disastro! Armaghedon!
Giovanni - Aspetta! Quello che è successo?
Monica - Abbiamo raggiunto un vicolo cieco. Le prestazioni delle nostre applicazioni sono ridicolmente lente! Per avere un rapporto, dobbiamo aspettare due giorni! Due giorni per generare effettivamente una dashboard per un cliente. Significa che ogni giorno dobbiamo aumentare la nostra coda di calcolo, mentre la nostra dashboard diventa sempre più obsoleta. Il nostro esperto DBA ha lavorato due mesi per ottimizzare alcune query, mentre la nostra struttura del database è un disastro completo. Ci sono sviluppatori che lo supportano, ma il problema è che il DBA sta pensando in SQL e gli sviluppatori stanno passando giorni cercando di tradurre questo in criteri separati o in formato HQL. Stiamo cercando di utilizzare l'SQL nativo il più possibile poiché le prestazioni sono fondamentali al momento. Ad ogni modo, non possiamo fare molto poiché lo schema del database sembra essere sbagliato. Sembrava giusto dal punto di vista orientato agli oggetti, ma sembra ridicolo da quello relazionale. Mi chiedo: come è successo? Gli sviluppatori ci stanno dicendo che cambiare la struttura delle entità sarà uno sforzo enorme, quindi non possiamo permettercelo. Ricordo che nel progetto precedente era un pasticcio, ma non siamo mai arrivati a un punto così critico. Siamo stati in grado di scrivere un'applicazione completamente diversa per lavorare con i dati. Ora, è rischioso modificare quelle tabelle generate poiché è davvero difficile assicurarsi che il modello di entità si comporti sempre correttamente. E questa non è nemmeno la parte peggiore! Per aumentare le prestazioni, dobbiamo risolvere non solo i problemi del database, ma anche i problemi dell'intero livello tra il nostro database e l'applicazione. È travolgente! Abbiamo questi nuovi ragazzi, sai, consulenti. Stanno cercando di estrarre i dati, inserirli in un altro archivio e quindi eseguire calcoli dall'esterno. Ci vuole tutto troppo tempo!
Giovanni - Non so cosa dire.
Monica - Vedi John; Non voglio biasimarti. Ho scelto Hibernate per risolvere tutti questi problemi, ma ora ho imparato che non è un proiettile d'argento. Il danno è stato fatto, ed è irreversibile. A dire il vero, vorrei chiederti una cosa: ho passato gli ultimi quattro anni della mia carriera a occuparmi di Hibernate . Sembra che non abbia un futuro nella mia attuale azienda. Mi potete aiutare?
Allora, qual è la lezione appresa?
John - Ehi, Peter, lascia che ti presenti Monica.
Peter - Ehi, Monica! Stiamo costruendo la nostra nuova prossima grande cosa sai. Sarà enorme! Vogliamo essere come Uber! Sai forse come la persistenza...
Monica - Non in letargo !
Incartare
Monica è un'esperta di ibernazione . Tuttavia, Hibernate in questo caso è stata una decisione sbagliata. Nel momento in cui ha scoperto che la sua soluzione si è trasformata in un problema più grande dell'originale, è stata la più grande minaccia per l'intero progetto.
I dati sono lo scopo centrale dell'applicazione e, che piaccia o no, interessano l'intera architettura. Come abbiamo appreso dalla storia, non utilizzare Hibernate solo perché la tua applicazione Java utilizza un database o per motivi sociali. Scegli una soluzione che abbracci la flessibilità. Ci sono molte opzioni per robusti wrapper JDBC, come JdbcTemplate o Fluent JDBC Wrapper. In alternativa, ci sono altre soluzioni potenti, come jOOQ.