¿Existe alguna buena biblioteca de creación de SQL dinámico en Java? [cerrado]

108

Cualquiera conoce alguna buena biblioteca de construcción de SQL para Java como Squiggle (parece que ya no se mantiene). Preferiblemente, un proyecto en desarrollo activo.

Preferiblemente con sintaxis como Zend_Db_Select , algo que permitirá realizar una consulta como

String query = db.select().from('products').order('product_id');
Vladislav Rastrusny
fuente
¿Puedo preguntar cuál es la ventaja de la sintaxis anterior frente a "SELECT f1..fn FROM products ORDER BY product_id"?
Itay Moav -Malimovka
4
@ ItayMoav-Malimovka, Bueno, al menos la sintaxis de la consulta SQL en mi caso (si tomamos JOOQ como ejemplo) está marcada en el momento de escribir el código. Tiene autocompletado de sintaxis completa que acelera la escritura de consultas y la hace más propensa a errores.
Vladislav Rastrusny
Estoy de acuerdo en que esto es algo que los IDE deberían mejorar.
Itay Moav -Malimovka
1
@ ItayMoav-Malimovka, bueno ... en el caso de JOOQ, si cambio algo en mi estructura de base de datos, mi código dejará de compilarse hasta que lo arregle de acuerdo con la nueva estructura de base de datos. Si tiene consultas como texto, saldrán rotas.
Vladislav Rastrusny
Como ejemplo: actualmente estoy trabajando en una aplicación que necesita crear declaraciones para trabajar en una enorme base de datos heredada. Muchas declaraciones comparten restricciones personalizadas que creamos mediante un DSL SQL. Gracias a eso, podemos crear fácilmente declaraciones que no se conocen en el momento de la compilación.
Rafael Winterhalter

Respuestas:

53

Querydsl y jOOQ son dos opciones populares.

ponzao
fuente
6
JOOQ es quizás una mejor opción para el desarrollo de SQL duro, pero Querydsl tiene una API más simple y también admite otros backends (JPA, JDO, Lucene, Mongodb, etc.); También estoy en la empresa detrás de Querydsl
Timo Westkämper
Usamos Querydsl SQL en algunos de nuestros proyectos internos. No tengo experiencia personal con jooq, pero he oído que está bastante bien.
ponzao
11
El problema con QueryDsl es que no puede usarlo como un generador de consultas puro, ya que no le proporciona la consulta generada en sí. Generará la consulta y la ejecutará por usted también. No puedes conseguir uno sin otro.
Abhinav Sarkar
5
Querydsl y jOOQ parecen ser las opciones más populares y maduras, sin embargo, hay una cosa a tener en cuenta: ambos se basan en el concepto de generación de código, donde las metaclases se generan para tablas y campos de bases de datos. Esto facilita un DSL agradable y limpio, pero se enfrenta a un problema al intentar crear consultas para bases de datos que solo se conocen en tiempo de ejecución, como en el ejemplo de OP anterior. Si bien jOOQ admite un enfoque basado en cadenas, existen algunas peculiaridades. La documentación de Querydsl no menciona si es posible no utilizar la generación de código. Por favor corrígeme si estoy equivocado.
Sven Jacobs
3
@SvenJacobs comentario muy antiguo, pero para actualizar, QueryDSL permite construir sql sin generación de código: stackoverflow.com/questions/21615956/…
Nagaraj Tantri
7

ddlutils es mi mejor opción: http://db.apache.org/ddlutils/api/org/apache/ddlutils/platform/SqlBuilder.html

aquí está el ejemplo de creación (maravilloso):

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
fuente
1
Tengo que volver a definir la columna aunque ya las definí en @Entity, así que dolor.
huuthang
6

Puedo recomendar jOOQ . Proporciona muchas características excelentes, también un DSL intuitivo para SQL y un enfoque de ingeniería inversa extremadamente personalizable.

jOOQ combina eficazmente SQL complejo, seguridad de tipos, generación de código fuente, registros activos, procedimientos almacenados, tipos de datos avanzados y Java en un DSL fluido e intuitivo.

Christopher Klewes
fuente
¿Lo usas? ¿Cómo lo encuentras?
Vladislav Rastrusny
3
Lo uso para generar código fuente personalizado desde DDL. ¡Está funcionando muy bien!
Christopher Klewes
"Aunque la biblioteca jOOQ tiene una gran API para construir declaraciones SQL, viene con un conjunto completo de herramientas para construir declaraciones, conectarse a bases de datos, escribir / leer modelos a / desde bases de datos, etc. Debido a la naturaleza actual de la aplicación de Android VM , hay un límite de referencia de método de 64k. jOOQ puede contener más de 10,000 métodos referenciados cuando está en uso. Esto puede no parecer mucho en comparación con el límite, pero si considera otras bibliotecas grandes de uso común (como Guava y Google Play Services) , alcanzar ese límite de 64k se vuelve mucho más fácil ". - android-arsenal.com/details/1/3202 :(
Tomáš Fejfar
3

API de criterios de Hibernate (aunque no SQL simple, pero muy potente y en desarrollo activo):

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
fuente
1
El problema es que no se asigna a SQL como tengo entendido, ¿verdad?
Vladislav Rastrusny
7
esto no genera SQL y es una pesadilla depurar cuando no sigue la regla del menor asombro (no funciona como se esperaba)
Genera SQL (al final) y no sorprende a nadie. Beneficio: es portátil a través de bases de datos.
Vladimir Dyuzhev
3
¿Cuál es el nivel de complejidad de la consulta que logró alcanzar con la API de criterios de JPA, sin hacer que la consulta sea completamente ilegible? ¿Tiene un ejemplo de una selección anidada en una cláusula IN/ EXISTS, o de una autounión usando alias para la Saleentidad, etc.? Tengo curiosidad
Lukas Eder
1
Los comentarios no dan mucho espacio para proporcionar ejemplos, pero puede revisarlos en docs.jboss.org/hibernate/core/3.5/reference/en/html/…
Vladimir Dyuzhev
0

Puede utilizar la siguiente biblioteca:

https://github.com/pnowy/NativeCriteria

La biblioteca está construida en la parte superior de "crear consulta sql" de Hibernate, por lo que admite todas las bases de datos compatibles con Hibernate (la sesión de Hibernate y los proveedores de JPA son compatibles). El patrón del constructor está disponible y así sucesivamente (mapeadores de objetos, mapeadores de resultados).

Puede encontrar los ejemplos en la página de github, la biblioteca está disponible en Maven central, por supuesto.

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
fuente
esto es más complicado que simplemente escribir el SQL a mano
EpicPandaForce
@EpicPandaForce Estoy de acuerdo para casos muy simples, pero la concatenación es mucho más complicada cuando necesita concanear esa cadena en función de condiciones muy complicadas donde hay un conjunto diferente de estas condiciones. Entonces, la cadena correctamente concatenada (como todas las adiciones, combinaciones, teniendo, parámetros establecidos, etc.) es un fastidio. Con la solución, tiene un constructor que se ocupará de esta complejidad por usted.
Przemek Nowak