Есть ли в Java хорошая библиотека динамического построителя SQL? [закрыто]

108

Кто-нибудь знает какую-нибудь хорошую библиотеку построителя SQL для Java, такую ​​как Squiggle (похоже, больше не поддерживается). Желательно проект в активной разработке.

Желательно с синтаксисом вроде Zend_Db_Select , что-то, что позволит сделать запрос вроде

String query = db.select().from('products').order('product_id');
Владислав Раструсный
источник
Могу я спросить, в чем преимущество приведенного выше синтаксиса перед "SELECT f1..fn FROM products ORDER BY product_id"?
Итай Моав -Малимовка 09
4
@ ItayMoav-Malimovka, ну хоть синтаксис SQL-запроса в моем случае (если мы возьмем JOOQ в качестве примера) проверяется в момент написания кода. У вас есть полное автозаполнение синтаксиса, которое ускоряет написание запроса и делает его более подверженным ошибкам.
Владислав Раструсный
Я согласен, что это то, что IDE должны улучшить.
Итай Моав -Малимовка
1
@ ItayMoav-Malimovka, ну ... в случае с JOOQ, если я что-то изменю в своей структуре БД, мой код просто перестанет компилироваться, пока я не исправлю это в соответствии с новой структурой БД. Если у вас есть запросы в виде текста, они останутся неработающими.
Владислав Раструсный
В качестве примера: в настоящее время я работаю над приложением, которое должно создавать операторы для работы с массивной устаревшей базой данных. Многие операторы разделяют настраиваемые ограничения, которые мы создаем с помощью SQL DSL. Благодаря этому мы можем легко создавать операторы, которые не известны во время компиляции.
Рафаэль Винтерхальтер

Ответы:

54

Querydsl и jOOQ - два популярных варианта.

Понзао
источник
6
JOOQ может быть лучшим выбором для хардкорной разработки SQL, но Querydsl имеет более простой API и поддерживает также другие серверные части (JPA, JDO, Lucene, Mongodb и т. Д.); Я также в компании Querydsl
Тимо Весткемпер
Мы используем Querydsl SQL в нескольких наших собственных проектах. У меня нет личного опыта использования jooq, но я слышал, что это вполне нормально.
ponzao
11
Проблема с QueryDsl заключается в том, что вы не можете использовать его как чистый генератор запросов, поскольку он не выдает вам сам сгенерированный запрос. Он сгенерирует запрос и выполнит его за вас. Одно без другого невозможно.
Abhinav Sarkar
5
Querydsl и jOOQ кажутся наиболее популярными и зрелыми вариантами, однако следует помнить об одном: оба основаны на концепции генерации кода, при которой метаклассы генерируются для таблиц и полей базы данных. Это способствует созданию красивого и чистого DSL, но сталкивается с проблемой при попытке создать запросы для баз данных, которые известны только во время выполнения, как в приведенном выше примере OP. Хотя jOOQ поддерживает подход на основе String, есть некоторые особенности. В документации Querydsl не упоминается, можно ли не использовать генерацию кода. Пожалуйста, поправьте меня, если я ошибаюсь.
Свен Джейкобс,
3
@SvenJacobs очень старый комментарий, но для обновления QueryDSL позволяет создавать sql без генерации кода: stackoverflow.com/questions/21615956/…
Nagaraj Tantri
7

ddlutils - мой лучший выбор: http://db.apache.org/ddlutils/api/org/apache/ddlutils/platform/SqlBuilder.html

вот пример создания (отличный):

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
источник
1
Мне нужно снова определить столбец, хотя я уже определил их в @Entity, так что боль.
huuthang
6

Могу порекомендовать jOOQ . Он предоставляет множество замечательных функций, а также интуитивно понятный DSL для SQL и чрезвычайно настраиваемый подход обратного проектирования.

jOOQ эффективно сочетает сложный SQL, безопасность типов, генерацию исходного кода, активные записи, хранимые процедуры, расширенные типы данных и Java в плавном, интуитивно понятном DSL.

Кристофер Клевес
источник
Вы им пользуетесь? Как вы его нашли?
Владислав Раструсный
3
Я использую его для создания собственного исходного кода из DDL. Отлично работает!
Кристофер Клевес,
«Хотя библиотека jOOQ имеет отличный API для создания операторов SQL, она поставляется с полным набором инструментов для создания операторов, подключения к базам данных, записи / чтения моделей в / из баз данных и т. Д. Из-за текущего характера виртуальной машины приложений Android. , существует предел ссылок на методы 64 КБ. jOOQ может содержать более 10 000 ссылочных методов при использовании. Это может показаться не таким уж большим по сравнению с лимитом, но если учесть другие широко используемые большие библиотеки (такие как Guava и Google Play Services) , становится намного проще достичь этого лимита в 64 КБ ". - android-arsenal.com/details/1/3202 :(
Томаш Фейфар
3

Hibernate Criteria API (хотя и не простой SQL, но очень мощный и находится в активной разработке):

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();
Владимир Дюжев
источник
1
Проблема в том, что он не отображается на SQL, как я понимаю, верно?
Владислав Раструсный
7
это не генерирует SQL и кошмар для отладки , когда он не следовать правилу наименьшего удивления (не работает , как ожидалось)
Он генерирует SQL (в конце) и никого не удивляет. Преимущество - переносимость между базами данных.
Владимир Дюжев,
3
Какого уровня сложности запроса вы достигли с помощью API критериев JPA, не сделав запрос совершенно нечитаемым? У вас есть пример вложенного выбора в предложении IN/ EXISTSили самосоединения с использованием псевдонимов для Saleобъекта и т. Д.? Мне любопытно
Лукас Эдер
1
В комментариях не так много места для примеров, но вы можете просмотреть их на docs.jboss.org/hibernate/core/3.5/reference/en/html/…
Владимир Дюжев
0

Вы можете использовать следующую библиотеку:

https://github.com/pnowy/NativeCriteria

Библиотека построена на основе Hibernate "create sql query", поэтому она поддерживает все базы данных, поддерживаемые Hibernate (поддерживаются сеанс Hibernate и поставщики JPA). Доступен шаблон построителя и т. Д. (Преобразователи объектов, преобразователи результатов).

Вы можете найти примеры на странице github, библиотека, конечно же, доступна в центре Maven.

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")));
Пшемек Новак
источник
это сложнее, чем просто написать SQL вручную
EpicPandaForce
@EpicPandaForce Я согласен для очень простых случаев, но конкатенация очень сложна, когда вам нужно объединить эту строку на основе очень сложных условий, где есть другой набор этих условий. Тогда правильно составленная строка (как и все добавления, объединения, наличие, набор параметров и т. Д.) Является проблемой. С решением у вас есть конструктор, который справится с этой сложностью за вас.
Прземек Новак