Gibt es eine gute dynamische SQL Builder-Bibliothek in Java? [geschlossen]

108

Jeder kennt eine gute SQL Builder-Bibliothek für Java wie Squiggle (anscheinend nicht mehr gepflegt). Vorzugsweise ein Projekt in aktiver Entwicklung.

Am besten mit einer Syntax wie Zend_Db_Select , die es ermöglicht, eine Abfrage wie zu erstellen

String query = db.select().from('products').order('product_id');
Vladislav Rastrusny
quelle
Darf ich fragen, was der Vorteil der obigen Syntax gegenüber "SELECT f1..fn FROM products ORDER BY product_id" ist?
Itay Moav -Malimovka
4
@ ItayMoav-Malimovka, Nun, zumindest die Syntax der SQL-Abfrage in meinem Fall (wenn wir JOOQ als Beispiel nehmen) wird zum Zeitpunkt des Schreibens von Code überprüft. Sie verfügen über eine automatische Vervollständigung der vollständigen Syntax, die das Schreiben von Abfragen beschleunigt und fehleranfälliger macht.
Vladislav Rastrusny
Ich bin damit einverstanden, dass IDEs verbessert werden sollten.
Itay Moav-Malimovka
1
@ ItayMoav-Malimovka, na ja ... im Fall von JOOQ wird mein Code nur dann kompiliert, wenn ich etwas in meiner DB-Struktur ändere, bis ich es gemäß der neuen DB-Struktur korrigiere. Wenn Sie Abfragen als Text haben, bleiben diese kaputt.
Vladislav Rastrusny
Als Beispiel: Ich arbeite derzeit an einer Anwendung, die Anweisungen erstellen muss, um an einer massiven Legacy-Datenbank arbeiten zu können. Viele Anweisungen haben benutzerdefinierte Einschränkungen, die wir von einem SQL-DSL erstellen. Dank dessen können wir leicht Anweisungen erstellen, die zur Kompilierungszeit nicht bekannt sind.
Rafael Winterhalter

Antworten:

53

Querydsl und jOOQ sind zwei beliebte Optionen.

ponzao
quelle
6
JOOQ ist vielleicht die bessere Wahl für die Hardcore-SQL-Entwicklung, aber Querydsl hat eine einfachere API und unterstützt auch andere Backends (JPA, JDO, Lucene, Mongodb usw.). Ich bin auch in der Firma hinter Querydsl
Timo Westkämper
Wir verwenden Querydsl SQL in einigen unserer internen Projekte. Ich habe keine persönliche Erfahrung mit Jooq, aber ich habe gehört, dass es ganz in Ordnung ist.
Ponzao
11
Das Problem mit QueryDsl ist, dass Sie es nicht als reinen Abfragegenerator verwenden können, da es Ihnen nicht die generierte Abfrage selbst liefert. Die Abfrage wird generiert und auch für Sie ausgeführt. Man kann nicht eins ohne das andere bekommen.
Abhinav Sarkar
5
Querydsl und jOOQ scheinen die beliebtesten und ausgereiftesten Optionen zu sein. Eines ist jedoch zu beachten: Beide basieren auf dem Konzept der Codegenerierung, bei dem Metaklassen für Datenbanktabellen und -felder generiert werden. Dies erleichtert ein schönes, sauberes DSL, stellt jedoch ein Problem dar, wenn versucht wird, Abfragen für Datenbanken zu erstellen, die nur zur Laufzeit bekannt sind, wie im obigen Beispiel des OP. Während jOOQ einen String-basierten Ansatz unterstützt, gibt es einige Macken. In der Dokumentation von Querydsl wird nicht erwähnt, ob die Codegenerierung nicht verwendet werden kann. Bitte korrigieren Sie mich, wenn ich falsch liege.
Sven Jacobs
3
@SvenJacobs sehr alter Kommentar, aber zum Aktualisieren erlaubt QueryDSL das Erstellen von SQL ohne Codegenerierung: stackoverflow.com/questions/21615956/…
Nagaraj Tantri
7

ddlutils ist meine beste Wahl: http://db.apache.org/ddlutils/api/org/apache/ddlutils/platform/SqlBuilder.html

Hier ist ein Beispiel erstellen (groovig):

Platform platform  = PlatformFactory.createNewPlatformInstance("oracle");//db2,...
//create schema    
def db =        new Database();
def t = new Table(name:"t1",description:"XXX");
def col1 = new Column(primaryKey:true,name:"id",type:"bigint",required:true);
t.addColumn(col1);
t.addColumn(new Column(name:"c2",type:"DECIMAL",size:"8,2"));
t.addColumn( new Column(name:"c3",type:"varchar"));
t.addColumn(new Column(name:"c4",type:"TIMESTAMP",description:"date"));        
db.addTable(t);
println platform.getCreateModelSql(db, false, false)

//you can read Table Object from  platform.readModelFromDatabase(....)
def sqlbuilder = platform.getSqlBuilder();
println "insert:"+sqlbuilder.getInsertSql(t,["id":1,c2:3],false);
println "update:"+sqlbuilder.getUpdateSql(t,["id":1,c2:3],false);
println "delete:"+sqlbuilder.getDeleteSql(t,["id":1,c2:3],false);
//http://db.apache.org/ddlutils/database-support.html
qxo
quelle
1
Ich muss die Spalte erneut definieren, obwohl ich sie bereits in @Entity definiert habe.
Huuthang
6

Ich kann jOOQ empfehlen . Es bietet viele großartige Funktionen, ein intuitives DSL für SQL und einen äußerst anpassbaren Reverse-Engineering-Ansatz.

jOOQ kombiniert effektiv komplexes SQL, Typensicherheit, Quellcodegenerierung, aktive Datensätze, gespeicherte Prozeduren, erweiterte Datentypen und Java in einem fließenden, intuitiven DSL.

Christopher Klewes
quelle
Benutzt du es? Wie findest Du es?
Vladislav Rastrusny
3
Ich verwende es, um benutzerdefinierten Quellcode aus DDL zu generieren. Es funktioniert großartig!
Christopher Klewes
"Obwohl die jOOQ-Bibliothek über eine hervorragende API zum Erstellen von SQL-Anweisungen verfügt, enthält sie eine ganze Reihe von Tools zum Erstellen von Anweisungen, zum Herstellen einer Verbindung mit Datenbanken, zum Schreiben / Lesen von Modellen in / aus Datenbanken usw. Aufgrund der aktuellen Natur der Androids-Anwendungs-VM Es gibt ein Referenzlimit für 64.000 Methoden. jOOQ kann bei Verwendung über 10.000 Methoden enthalten, auf die verwiesen wird. Dies scheint im Vergleich zum Limit nicht viel zu sein, aber wenn Sie andere große Bibliotheken berücksichtigen, die häufig verwendet werden (wie Guava und Google Play Services). Das Erreichen dieses 64k-Limits wird viel einfacher. " - android-arsenal.com/details/1/3202 :(
Tomáš Fejfar
3

Hibernate Criteria API (zwar kein einfaches SQL, aber sehr leistungsfähig und in aktiver Entwicklung):

List sales = session.createCriteria(Sale.class)
         .add(Expression.ge("date",startDate);
         .add(Expression.le("date",endDate);
         .addOrder( Order.asc("date") )
         .setFirstResult(0)
         .setMaxResults(10)
         .list();
Vladimir Dyuzhev
quelle
1
Das Problem ist, dass es nicht nach meinem Verständnis SQL zugeordnet ist, oder?
Vladislav Rastrusny
7
Dies generiert kein SQL und ist ein Albtraum zum Debuggen, wenn es nicht der Regel des geringsten Erstaunens folgt (funktioniert nicht wie erwartet)
Es generiert SQL (am Ende) und überrascht niemanden. Vorteil - es ist datenbankübergreifend portierbar.
Vladimir Dyuzhev
3
Welchen Grad an Abfragekomplexität haben Sie mit der JPA Criteria API erreicht, ohne die Abfrage völlig unlesbar zu machen? Haben Sie ein Beispiel für eine verschachtelte Auswahl in einer IN/ EXISTS-Klausel oder für einen Self-Join unter Verwendung von Aliasen für die SaleEntität usw.? Ich bin neugierig
Lukas Eder
1
Kommentare geben nicht viel Platz, um die Beispiele bereitzustellen, aber Sie können sie gerne unter docs.jboss.org/hibernate/core/3.5/reference/en/html/…
Vladimir Dyuzhev
0

Sie können die folgende Bibliothek verwenden:

https://github.com/pnowy/NativeCriteria

Die Bibliothek basiert auf dem Ruhezustand "SQL-Abfrage erstellen" und unterstützt alle von Hibernate unterstützten Datenbanken (die Hibernate-Sitzung und JPA-Anbieter werden unterstützt). Das Builder-Muster ist verfügbar usw. (Objektzuordnungen, Ergebniszuordnungen).

Sie finden die Beispiele auf der Github-Seite, die Bibliothek ist natürlich bei Maven Central erhältlich.

NativeCriteria c = new NativeCriteria(new HibernateQueryProvider(hibernateSession), "table_name", "alias");
c.addJoin(NativeExps.innerJoin("table_name_to_join", "alias2", "alias.left_column", "alias2.right_column"));
c.setProjection(NativeExps.projection().addProjection(Lists.newArrayList("alias.table_column","alias2.table_column")));
Przemek Nowak
quelle
Dies ist komplizierter als nur das Schreiben der SQL von Hand
EpicPandaForce
@EpicPandaForce Ich stimme für sehr einfache Fälle zu, aber die Verkettung ist sehr kompliziert, wenn Sie diese Zeichenfolge basierend auf sehr komplizierten Bedingungen, bei denen es einen anderen Satz dieser Bedingungen gibt, verketten müssen. Die korrekt verkettete Zeichenfolge (wie alle Adds, Joins, Have, Parameterset usw.) ist dann ein Schmerz. Mit der Lösung haben Sie einen Builder, der diese Komplexität für Sie erledigt.
Przemek Nowak