Existe-t-il une bonne bibliothèque de générateur SQL dynamique en Java? [fermé]

108

Tout le monde connaît une bonne bibliothèque SQL Builder pour Java comme Squiggle (qui ne semble plus maintenue). De préférence, un projet en développement actif.

De préférence avec une syntaxe comme Zend_Db_Select , quelque chose qui permettra de faire une requête comme

String query = db.select().from('products').order('product_id');
Vladislav Rastrusny
la source
Puis-je demander quel est l'avantage de la syntaxe ci-dessus par rapport à "SELECT f1..fn FROM produits ORDER BY product_id"?
Itay Moav -Malimovka
4
@ ItayMoav-Malimovka, Eh bien, au moins la syntaxe de la requête SQL dans mon cas (si nous prenons JOOQ comme exemple) est vérifiée au moment où vous écrivez du code. Vous disposez d'une saisie semi-automatique de la syntaxe qui accélère l'écriture de vos requêtes et la rend plus sujette aux erreurs.
Vladislav Rastrusny
Je suis d'accord que c'est quelque chose que les IDE devraient améliorer.
Itay Moav -Malimovka
1
@ ItayMoav-Malimovka, eh bien ... dans le cas de JOOQ, si je change quelque chose dans ma structure de base de données, mon code arrêtera simplement de se compiler jusqu'à ce que je le corrige selon la nouvelle structure de base de données. Si vous avez des requêtes sous forme de texte, elles seront interrompues.
Vladislav Rastrusny
À titre d'exemple: je travaille actuellement sur une application qui a besoin de créer des déclarations pour travailler sur une base de données héritée massive. De nombreuses instructions partagent des contraintes personnalisées que nous construisons par un SQL DSL. Grâce à cela, nous pouvons facilement créer des instructions qui ne sont pas connues au moment de la compilation.
Rafael Winterhalter

Réponses:

54

Querydsl et jOOQ sont deux choix populaires.

ponzao
la source
6
JOOQ est peut-être un meilleur choix pour le développement SQL hardcore, mais Querydsl a une API plus simple et prend également en charge d'autres backends (JPA, JDO, Lucene, Mongodb etc.); Je suis également dans l'entreprise derrière Querydsl
Timo Westkämper
Nous utilisons Querydsl SQL dans quelques-uns de nos projets internes. Je n'ai aucune expérience personnelle de jooq mais j'ai entendu dire que tout allait bien.
ponzao
11
Le problème avec QueryDsl est que vous ne pouvez pas l'utiliser comme un pur générateur de requêtes car il ne vous donne pas la requête générée elle-même. Il générera la requête et l'exécutera pour vous aussi. Vous ne pouvez pas en avoir un sans un autre.
Abhinav Sarkar
5
Querydsl et jOOQ semblent être les choix les plus populaires et les plus matures, mais il y a une chose à savoir: les deux reposent sur le concept de génération de code, où des méta-classes sont générées pour les tables et les champs de la base de données. Cela facilite un DSL agréable et propre, mais il se heurte à un problème lorsque vous essayez de créer des requêtes pour des bases de données qui ne sont connues qu'au moment de l'exécution, comme dans l'exemple de l'OP ci-dessus. Alors que jOOQ prend en charge une approche basée sur une chaîne, il y a quelques bizarreries. La documentation de Querydsl ne mentionne pas s'il est possible de ne pas utiliser la génération de code. Corrigez-moi si j'ai tort, s'il-vous plait.
Sven Jacobs
3
@SvenJacobs très vieux commentaire, mais pour mettre à jour, QueryDSL permet de construire SQL sans génération de code: stackoverflow.com/questions/21615956
...
7

ddlutils est mon meilleur choix: http://db.apache.org/ddlutils/api/org/apache/ddlutils/platform/SqlBuilder.html

voici un exemple de création (groovy):

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
la source
1
Je dois redéfinir la colonne bien que je les ai déjà définies dans @Entity, donc douleur.
huuthang
6

Je peux recommander jOOQ . Il fournit de nombreuses fonctionnalités intéressantes, également un DSL intuitif pour SQL et une approche de rétro-ingénierie extrêmement personnalisable.

jOOQ combine efficacement SQL complexe, sécurité des types, génération de code source, enregistrements actifs, procédures stockées, types de données avancés et Java dans un DSL fluide et intuitif.

Christopher Klewes
la source
L'utilisez vous? Comment tu le trouves?
Vladislav Rastrusny
3
Je l'utilise pour générer un code source personnalisé à partir de DDL. Cela fonctionne très bien!
Christopher Klewes
«Bien que la bibliothèque jOOQ dispose d'une excellente API pour créer des instructions SQL, elle est livrée avec une suite complète d'outils pour créer des instructions, se connecter à des bases de données, écrire / lire des modèles vers / depuis des bases de données, etc. En raison de la nature actuelle de la machine virtuelle d'application Androids , il existe une limite de référence de méthode de 64 Ko. jOOQ peut contenir plus de 10 000 méthodes référencées lors de son utilisation. Cela peut ne pas sembler beaucoup par rapport à la limite, mais si vous considérez d'autres grandes bibliothèques couramment utilisées (telles que les services Guava et Google Play) , atteindre cette limite de 64 000 devient beaucoup plus facile. " - android-arsenal.com/details/1/3202 :(
Tomáš Fejfar
3

API Hibernate Criteria (pas SQL simple, mais très puissant et en développement actif):

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
la source
1
Le problème est qu'il ne correspond pas à SQL si je comprends bien, non?
Vladislav Rastrusny
7
cela ne génère pas de SQL et est un cauchemar à déboguer quand il ne suit pas la règle du moindre étonnement (ne fonctionne pas comme prévu)
Cela génère du SQL (à la fin) et cela ne surprend personne. Avantage - il est portable entre les bases de données.
Vladimir Dyuzhev le
3
Quel est le niveau de complexité de requête que vous avez atteint avec l'API JPA Criteria, sans rendre la requête totalement illisible? Avez-vous un exemple de sélection imbriquée dans une clause IN/ EXISTS, ou d'une auto-jointure utilisant des alias pour l' Saleentité, etc.? Je suis curieux
Lukas Eder
1
Les commentaires ne laissent pas beaucoup d'espace pour fournir les exemples, mais vous pouvez les consulter sur docs.jboss.org/hibernate/core/3.5/reference/en/html
Vladimir Dyuzhev
0

Vous pouvez utiliser la bibliothèque suivante:

https://github.com/pnowy/NativeCriteria

La bibliothèque est construite sur le dessus de la "requête de création SQL" d'Hibernate et prend donc en charge toutes les bases de données prises en charge par Hibernate (la session Hibernate et les fournisseurs JPA sont pris en charge). Le modèle de générateur est disponible et ainsi de suite (mappeurs d'objets, mappeurs de résultats).

Vous pouvez trouver les exemples sur la page github, la librairie est bien sûr disponible chez Maven central.

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
la source
c'est plus compliqué que d'écrire simplement le SQL à la main
EpicPandaForce
@EpicPandaForce Je suis d'accord pour des cas très simples mais la concaténation est beaucoup plus compliquée lorsque vous devez concaténer cette chaîne en fonction de conditions très compliquées où il existe un ensemble différent de ces conditions. La chaîne correctement concaténée (comme tous les ajouts, jointures, avoir, paramètres définis, etc.) est une douleur. Avec la solution, vous disposez d'un constructeur qui s'occupera de cette complexité pour vous.
Przemek Nowak