Existe alguma boa biblioteca de construtor SQL dinâmico em Java? [fechadas]

108

Qualquer um conhece alguma boa biblioteca SQL builder para Java como o Squiggle (parece que não é mais mantida). De preferência, um projeto em desenvolvimento ativo.

De preferência com sintaxe como Zend_Db_Select , algo que permitirá fazer uma consulta como

String query = db.select().from('products').order('product_id');
Vladislav Rastrusny
fonte
Posso perguntar qual é a vantagem da sintaxe acima em relação a "SELECT f1..fn FROM produtos ORDER BY product_id"?
Itay Moav -Malimovka
4
@ ItayMoav-Malimovka, Bem, pelo menos a sintaxe da consulta SQL no meu caso (se tomarmos JOOQ como exemplo) é verificada no momento em que você escreve o código. Você tem o preenchimento automático de sintaxe completo, o que acelera a escrita de sua consulta e a torna mais sujeita a erros.
Vladislav Rastrusny
Eu concordo que isso é algo que os IDEs deveriam melhorar.
Itay Moav -Malimovka
1
@ ItayMoav-Malimovka, bem ... no caso do JOOQ, se eu mudar algo na estrutura do meu banco de dados, meu código irá apenas parar de compilar até que eu conserte de acordo com a nova estrutura do banco de dados. Se você tiver consultas como um texto, elas sairão quebradas.
Vladislav Rastrusny
Por exemplo: Atualmente estou trabalhando em um aplicativo que precisa criar instruções para funcionar em um enorme banco de dados legado. Muitas instruções compartilham restrições personalizadas que construímos por uma DSL SQL. Graças a isso, podemos criar facilmente instruções que não são conhecidas em tempo de compilação.
Rafael Winterhalter

Respostas:

53

Querydsl e jOOQ são duas escolhas populares.

Ponzao
fonte
6
JOOQ é talvez a melhor escolha para desenvolvimento de SQL hardcore, mas Querydsl tem uma API mais simples e também suporta outros back-ends (JPA, JDO, Lucene, Mongodb etc.); Também estou na empresa por trás da Querydsl
Timo Westkämper
Usamos Querydsl SQL em alguns de nossos projetos internos. Não tenho experiência pessoal com jooq, mas ouvi dizer que está tudo bem.
ponzao
11
O problema com QueryDsl é que você não pode usá-lo como um gerador de consulta puro, pois ele não fornece a consulta gerada em si. Ele irá gerar a consulta e executá-la para você também. Você não consegue um sem o outro.
Abhinav Sarkar
5
Querydsl e jOOQ parecem ser as escolhas mais populares e maduras, no entanto, há uma coisa a se estar ciente: ambos contam com o conceito de geração de código, onde meta classes são geradas para tabelas e campos do banco de dados. Isso facilita um DSL bom e limpo, mas enfrenta um problema ao tentar criar consultas para bancos de dados que são conhecidos apenas em tempo de execução, como no exemplo do OP acima. Embora jOOQ suporte uma abordagem baseada em String, existem algumas peculiaridades. A documentação do Querydsl não menciona se é possível não usar a geração de código. Por favor me corrija se eu estiver errado.
Sven Jacobs
3
@SvenJacobs comentário muito antigo, mas para atualizar, QueryDSL permite construir sql sem geração de código: stackoverflow.com/questions/21615956/…
Nagaraj Tantri
7

ddlutils é minha melhor escolha: http://db.apache.org/ddlutils/api/org/apache/ddlutils/platform/SqlBuilder.html

aqui está o exemplo de criação (bacana):

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
fonte
1
Tenho que definir coluna novamente, embora já tenha definido no @Entity, então dor.
huuthang
6

Posso recomendar o jOOQ . Ele fornece muitos recursos excelentes, também uma DSL intuitiva para SQL e uma abordagem de engenharia reversa extremamente usual.

O jOOQ combina de forma eficaz SQL complexo, segurança de tipos, geração de código-fonte, registros ativos, procedimentos armazenados, tipos de dados avançados e Java em um DSL intuitivo e fluente.

Christopher Klewes
fonte
Você usa isso? Como você encontra isso?
Vladislav Rastrusny
3
Eu o uso para gerar código-fonte personalizado de DDL. Está funcionando muito bem!
Christopher Klewes,
"Embora a biblioteca jOOQ tenha uma ótima API para construir declarações SQL, ela vem com um conjunto completo de ferramentas para construir declarações, conectar-se a bancos de dados, escrever / ler modelos de / para bancos de dados, etc. Devido à natureza atual do aplicativo Androids VM , há um limite de referência de método de 64k. jOOQ pode conter mais de 10.000 métodos referenciados quando em uso. Isso pode não parecer muito em comparação com o limite, mas se você considerar outras grandes bibliotecas comumente usadas (como Guava e Google Play Services) , atingir o limite de 64k se torna muito mais fácil. " - android-arsenal.com/details/1/3202 :(
Tomáš Fejfar
3

API de critérios do Hibernate (embora não seja SQL puro, mas muito poderosa e em desenvolvimento ativo):

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
fonte
1
O problema é que não mapeia para SQL pelo que entendi, certo?
Vladislav Rastrusny
7
isso não gera SQL e é um pesadelo para depurar quando não segue a regra do menor espanto (não funciona como esperado)
Ele gera SQL (no final) e não surpreende ninguém. Benefício - é portátil entre bancos de dados.
Vladimir Dyuzhev
3
Qual é o nível de complexidade de consulta que você conseguiu atingir com a API de critérios JPA, sem tornar a consulta totalmente ilegível? Você tem um exemplo de um select aninhado em uma cláusula IN/ EXISTS, ou de uma self-join usando aliases para a Saleentidade, etc? Estou curioso
Lukas Eder,
1
Os comentários não dão muito espaço para fornecer os exemplos, mas você pode analisá-los em docs.jboss.org/hibernate/core/3.5/reference/en/html/…
Vladimir Dyuzhev
0

Você pode usar a seguinte biblioteca:

https://github.com/pnowy/NativeCriteria

A biblioteca é construída no topo do Hibernate "criar consulta sql" para que suporte todos os bancos de dados suportados pelo Hibernate (a sessão Hibernate e provedores JPA são suportados). O padrão do construtor está disponível e assim por diante (mapeadores de objetos, mapeadores de resultados).

Você pode encontrar os exemplos na página do github, a biblioteca está disponível na central do Maven, é claro.

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
fonte
isso é mais complicado do que apenas escrever o SQL à mão
EpicPandaForce
@EpicPandaForce Eu concordo para casos muito simples, mas a concatenação é muito complicada quando você precisa concatá-la com base em condições muito complicadas onde existe um conjunto diferente dessas condições. A string concatenada corretamente (como todas as adições, junções, ter, conjunto de parâmetros, etc.) é uma dor. Com a solução você tem um construtor que vai lidar com essa complexidade para você.
Przemek Nowak