Cosa penseresti di un nuovo strumento di persistenza Java, che in realtà non è un ORM? [chiuso]


12

Persistenza in Java

Negli ultimi anni, ho acquisito esperienza nel campo dell'astrazione della persistenza in Java, usando concetti come EJB 2.0, Hibernate, JPA e quelli coltivati ​​in casa. Mi sembravano avere una curva di apprendimento ripida e molta complessità. Inoltre, come grande fan di SQL, ho anche pensato che molti modelli di astrazione forniscono troppa astrazione su SQL, creando concetti come "criteri", "predicati", "restrizioni" che sono concetti molto buoni, ma non SQL.

L'idea generale di astrazione della persistenza in Java sembra essere basata sul modello relazionale agli oggetti, in cui RDBMS è in qualche modo abbinato al mondo OO. Il dibattito ORM è sempre stato emotivo, in quanto non sembra esistere un'unica soluzione adatta a tutti, se tale soluzione può persino esistere.

jOOQ

La mia preferenza personale su come evitare i problemi relativi all'ORM è attenersi al mondo relazionale. Ora la scelta del paradigma del modello di dati non dovrebbe essere l'argomento di discussione in quanto è una preferenza personale o una questione di quale modello di dati si adatta meglio a un problema concreto. La discussione che vorrei iniziare riguarda il mio strumento di persistenza chiamato jOOQ . Ho progettato jOOQ per offrire la maggior parte dei vantaggi dei moderni strumenti di persistenza:

  • Un linguaggio specifico di dominio basato su SQL
  • Generazione di codice sorgente mappando lo schema del database sottostante su Java
  • Supporto per molti RDBMS

Aggiunta di alcune funzionalità che pochi moderni strumenti di persistenza hanno (correggimi se sbaglio):

  • Supporto per SQL complessi: unioni, selezioni nidificate, self-join, aliasing, clausole case, espressioni aritmetiche
  • Supporto per SQL non standard: stored procedure, UDT, ENUMS, funzioni native, funzioni analitiche

Si prega di considerare la pagina della documentazione per maggiori dettagli: http://www.jooq.org/learn.php . Vedrai che un approccio molto simile è implementato in Linq per C #, sebbene Linq non sia progettato esclusivamente per SQL.

La domanda

Ora, detto che sono un grande fan di SQL, mi chiedo se altri sviluppatori condivideranno il mio entusiasmo per jOOQ (o Linq). Questo tipo di approccio all'astrazione della persistenza è praticabile? Quali sono i vantaggi / gli svantaggi che potresti vedere? Come potrei migliorare jOOQ e cosa manca secondo te? Dove ho sbagliato, concettualmente o praticamente?

Sono state apprezzate risposte critiche ma costruttive

Capisco che il dibattito è emotivo. Ci sono molti ottimi strumenti là fuori che fanno già cose simili. Quello che mi interessa è un feedback critico ma costruttivo, basato sulla tua esperienza o articoli che potresti aver letto.


Gestisce le transazioni?
Armand,

@Alison: No, si tratta solo di SQL. La gestione delle transazioni è un'attività molto complessa che penso che molti altri strumenti / framework (incluso EJB2 / 3) gestiranno meglio di jOOQ
Lukas Eder,

Consiglio vivamente un caso d'uso molto solido e dettagliato in cui mostri che il tuo approccio è eccellente per risolverlo.

Inoltre, la modifica di QUESTO pesante renderà le risposte più o meno irrilevanti e quindi inutilizzabili per i futuri lettori. Poni invece una domanda nuova e migliore.

Ciao Thorbjorn. Intendi un caso d'uso diverso da quelli mostrati nella pagina degli esempi? O ti piacerebbe vedere alcuni esempi nella domanda stessa? Informazioni sulla modifica: hai ragione in generale. In questo caso, tuttavia, ho pensato che le due risposte che avrei avuto finora sarebbero state un po 'le stesse ...
Lukas Eder,

Risposte:


5

Penso che tu sia sulla strada giusta e che dovresti continuare con la tua soluzione. Alcune delle precedenti critiche sono eccessivamente dure, ma vengono fatti alcuni punti validi.

Anch'io ho cercato a lungo e duramente una soluzione ORM completa che si adattasse alle mie esigenze, ma ogni soluzione che ho esaminato è venuta meno. Ognuno ha i suoi pro e contro, ma nessuno ha fatto davvero tutto quello che volevo. Concordo con la tua critica a queste soluzioni, vale a dire che generalmente sono complesse e hanno una curva di apprendimento ripida.

Il contendente principale dovrebbe essere lo standard di fatto, Hibernate. È completo, robusto e ben testato. Lo rispetto e lo apprezzo per quello che è. Ora, a rischio di offendere metà della comunità di programmazione, devo anche dire che è un pezzo gonfio e complesso di codice non performante. Ho trascorso un bel po 'di tempo a frugare nelle sue viscere, cercando di eseguire il debug e capirlo, e non sono rimasto colpito da ciò che ho visto. Detto questo, lo consiglierei comunque come punto di partenza per chiunque cerchi un buon ORM. Si distingue per il semplice CRUD, ma non lo userei per query di massa performanti, come il data mining o il crunching dei numeri.

Sfortunatamente, la mia applicazione è più della varietà dei numeri (anche se c'è anche un po 'di CRUD), quindi ho deciso di lanciare la mia. Sapevo fin dall'inizio che sarebbe stato inferiore rispetto alle altre soluzioni là fuori, ma sarebbe stato abbastanza buono e mi avrebbe dato le prestazioni di cui avevo bisogno. Ora ecco la parte davvero fantastica: sembra proprio la tua soluzione!

Questo è quello che penso tu abbia fatto bene: hai dichiarato le tue convinzioni sottostanti come una sorta di dichiarazione di missione, e quelle credenze sono corrette. Ovviamente ho passato parecchio tempo a pensare anche a questo problema, ed è difficile da risolvere. Ma col passare del tempo, penso che la comunità di programmatori capisca meglio e creeremo soluzioni migliori. Complimenti per tutti gli sforzi precedenti (soprattutto Hibernate), ma penso che possiamo fare di meglio.

La tua soluzione affina meglio il problema, ma ne risolve solo una parte. Penso che un approccio stratificato possa darci tutto ciò che vogliamo. Quello che hai ideato / IMO è il livello di fondazione. Come hai suggerito, penso che questo livello venga generato automaticamente in base a uno schema di database. Dovrebbe essere un modello a oggetti relazionale molto semplice che viene mappato direttamente sul database e non di più. Hai ragione sul fatto che i dati persistono molto più a lungo del codice, quindi a questo livello i dati dovrebbero guidare il codice e non viceversa. Supporterebbe il CRUD e le query in blocco performanti. Probabilmente implementerei una specie di cache L1 a questo livello.

Tuttavia, la cosa che eccellono in altre soluzioni ORM è la capacità di definire i tuoi oggetti in un modo che non dipende molto dalla struttura effettiva del database sottostante. Per questa funzionalità, vorrei creare un altro livello. Per necessità questo livello diventa più astratto, si spera più semplice (a scapito della perdita di funzionalità), e si basa sul livello precedente. Potrebbe utilizzare una cache L2.

Sono aperto ad avere più livelli, ma il punto chiave per me è che fornendo più punti di ingresso nella libreria, puoi soddisfare ogni esigenza. Per coloro che desiderano una soluzione CRUD semplice che si associ direttamente agli oggetti di propria scelta, possono costruire sul livello superiore. Per coloro che cercano qualcosa di più potente e performante ma disposti a sostenere la complessità aggiuntiva, possono collegarsi al livello inferiore. Non vorrei creare un linguaggio di query speciale, ma esporrei l'oggetto del generatore di query per questo scopo. E poiché il codice è stratificato, quella funzionalità esiste naturalmente senza pass-through speciale.

Penso che tu abbia una comprensione dello spazio e non stai reinventando la ruota ma piuttosto abbia colpito una nicchia leggermente diversa. E francamente, questa è una ruota che potrebbe comunque migliorare. Ti trovi ad affrontare una battaglia in salita contesa contro centrali del passato, ma se la tua soluzione è buona e penso che stia andando in quel modo, allora guadagnerà popolarità per i suoi meriti.


Ciao Dale, grazie per il tuo incoraggiamento! Mi piace il tuo modo di dire che i livelli e jOOQ sono sul livello più basso con ulteriore astrazione possibile sopra jOOQ. Questo è qualcosa che voglio affrontare quando ho abbastanza slancio con jOOQ. L'interfaccia con JPA e / o Hibernate sarà chiaramente sulla tabella di marcia. Come dici tu, questi strumenti eccellono nella semplicità attraverso l'astrazione e hanno molte funzionalità che non voglio nel mio livello: transazioni, sessioni, cache L2, ecc. PS: La tua soluzione è di dominio pubblico? Sarei molto interessato!
Lukas Eder,

8

"Ci sono molti proiettili magici là fuori e non mancano gli sviluppatori ingenui".

Senza offesa, sembra che tu non capisca del tutto ciò che è già stato fatto in questo spazio e quindi stai reinventando alcune ruote: l'esperienza ci direbbe che tutte le ruote che inventi, pur essendo pulite e divertenti, non sono probabilmente così buono o utile come le ruote ben rifinite già disponibili.


1
Grazie per il tuo feedback! Hai dato uno sguardo più approfondito alla mia biblioteca? Cerco esattamente di "abbandonare la O" come lo chiama il tuo articolo. jOOQ vuole che gli sviluppatori scrivano codice SQL, non OR-Mapped. Cerco di ottenere ciò che Linq fa per .NET senza riuscire a riscrivere il compilatore Java. Congratulazioni a Microsoft per Linq! E oso dire che non sono ingenuo, perché ho creato jOOQ dopo che non ero soddisfatto di EJB 2.0 (un po 'di tempo fa), né di Hibernate. Proprio per i motivi indicati nel tuo articolo. Ho provato quello che è stato fatto e non è stato adatto alle mie esigenze.
Lukas Eder,

jOOQ vuole che gli sviluppatori utilizzino la tua API simile ai criteri. Questo non è SQL. È un modo per creare SQL che in realtà è più brutto e più complicato di SQL con pochissimi benefici reali. "q.addCompareCondition (TAuthor.YEAR_OF_BIRTH, 1920, Comparator.GREATER);" Non vedo nulla di veramente diverso da qualsiasi altro strumento di generazione di classi per tabella. Il che significa che, come ho detto, c'è una probabilità quasi certa che ne esiste già una migliore. I campi stringa generati dal modello non si avvicinano nemmeno a ciò che abilitano le espressioni lambda.
Quentin-starin,

1
È un po 'difficile per me capire la motivazione dietro la tua risposta / commento. Penso ancora che tu non abbia avuto uno sguardo approfondito agli esempi che ho fornito (hai citato il primo esempio) e il tuo confronto con prodotti concorrenti mi sembra in qualche modo vago. Il punto della mia domanda era di ottenere un feedback costruttivo, e apprezzerei proprio questo. Citi "strumenti migliori" ed "espressioni lambda". Potresti per favore elaborare? Come si confronta jOOQ con gli strumenti che hai citato? Come vengono implementate le espressioni lambda in Java 6, prima che Oracle possa aggiungerle in Java 8? Grazie ancora
Lukas Eder il

2

Uno scenario che renderebbe adatto questo tipo di API è quando hai bisogno di un builder SQL indipendente dal database che la maggior parte degli ORM non ti consente di avere. Una grande situazione in cui ne ho avuto bisogno è nel generare rapporti. Ho avuto bisogno di costruire SQL in modo orientato agli oggetti e andando a eseguire questo sql su vari database per i test. Hibernate e altri ORM dipendono molto dalle configurazioni, limitando così la mia costruzione sql in modo che non riesca a combinare la tabella in cui l'associazione non esiste negli xmls. Dato che nel Modulo di report che sto sviluppando è possibile qualsiasi associazione, ho cercato qualcosa di diverso. Poi mi sono imbattuto in JOOQ. Risolve solo il mio problema. Ho solo bisogno di un accesso in sola lettura, non ho mai avuto problemi di debug dolorosi come in ibernazione.

In realtà sto progettando di sviluppare un modo diverso di modellare i dati piuttosto che il modo POJO comune e usare JOOQ come una delle basi che è un livello per costruire SQL. Quindi, oltre a JOOQ, sto progettando di creare un modo più flessibile di modellare dati / entità utilizzando HashMaps. Il mio design consentirebbe di integrare più facilmente front end e backend in un unico punto di ingresso, anche se utilizzerei vari livelli per completare il framework, proprio come hanno detto i commenti sopra. JOOQ svolgerà davvero un ruolo molto buono come nel mio progetto, funge da base o pilastro.

Quindi continuate così Lukas!


1

Se capisco correttamente il tuo strumento, associa gli oggetti direttamente a un framework SQL concettuale anziché mappare gli oggetti che implementano un po 'di mapping con la funzionalità SQL (ORM), quasi come un ORM: astrazione per un maggiore controllo geniale in modo da poter utilizzare più funzionalità SQL Di solito gli ORM non ti danno?

Non sono sicuro di quale problema stai cercando di risolvere. Dal momento che il tuo strumento richiede una conoscenza approfondita di SQL, le persone non utilizzerebbero, beh, SQL? È il codice colla che stai cercando di eliminare? Migliore convalida delle query SQL tramite la modellazione API anziché semplici stringhe?

Devo ammettere che i tuoi esempi JOOQ sembrano versioni LISP dell'SQL. Non è una brutta cosa :) e vedo che alcune delle cose avanzate sono interessanti, ma i vantaggi che elenchi lentamente scompaiono man mano che diventi sempre più avanzato (più configurazione, meno astratto, più radicato nel santuario interno dello specifico SQL motore, ecc.)

Un suggerimento che mi piacerebbe vedere che mi manca nella maggior parte degli ORM è un framework in grado di gestire gli oggetti in modo non relazionale, traducendo le interazioni degli oggetti in qualunque sia il backend (SQL, NoSQL, Topic Maps, RDF, ecc. .) che richiede la memorizzazione nella cache del Modello utilizzato piuttosto che i dettagli delle interazioni SQL, dei dialetti e del pensiero relazionale.

IMHO, ovviamente. :)


Ciao, grazie per il tuo feedback. Hai capito bene. Come diceva qstarin, provo a rimuovere la "O" da ORM e rimanere relazionale. Perché non semplice SQL? Intendi JDBC? Hai mai interrogato il tuo database con 5 selezioni nidificate e diversi join, funzioni analitiche con JDBC? Errori di sintassi, mancata corrispondenza del binding, ecc. Sfortunatamente, jOOQ non può essere lo strumento giusto per te, perché non esiste alcuna possibilità di mappare QUALSIASI modello su oggetti. E non lo voglio. jOOQ DOVREBBE essere relazionale. Per quegli sviluppatori che preferiscono quel modo di pensare. Per l'altro consiglio JPA .. O Linq se stai facendo .NET
Lukas Eder il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.