Czy w Javie jest jakaś dobra biblioteka do tworzenia dynamicznego SQL? [Zamknięte]


108

Każdy zna dobrą bibliotekę SQL Builder dla Javy, taką jak Squiggle (wydaje się, że nie jest już utrzymywana). Najlepiej projekt w fazie aktywnego rozwoju.

Najlepiej ze składnią taką jak Zend_Db_Select , czymś, co pozwoli na wykonanie zapytania podobnego

String query = db.select().from('products').order('product_id');

Czy mogę zapytać, jaka jest zaleta powyższej składni w porównaniu z „SELECT f1..fn FROM products ORDER BY product_id”?
Itay Moav -Malimovka

4
@ ItayMoav-Malimovka, Cóż, przynajmniej składnia zapytania SQL w moim przypadku (jeśli weźmiemy jako przykład JOOQ) jest sprawdzana podczas pisania kodu. Masz pełne autouzupełnianie składni, które przyspiesza pisanie zapytań i czyni je bardziej podatnymi na błędy.
Vladislav Rastrusny

Zgadzam się, że jest to coś, co IDE powinno poprawić.
Itay Moav -Malimovka

1
@ ItayMoav-Malimovka, cóż ... w przypadku JOOQ, jeśli zmienię coś w mojej strukturze DB, mój kod po prostu przestanie kompilować, dopóki nie naprawię go zgodnie z nową strukturą DB. Jeśli masz zapytania jako tekst, pozostaną one uszkodzone.
Vladislav Rastrusny

Na przykład: obecnie pracuję nad aplikacją, która musi tworzyć instrukcje, aby pracować na ogromnej, starszej bazie danych. Wiele instrukcji ma wspólne ograniczenia, które tworzymy za pomocą SQL DSL. Dzięki temu w łatwy sposób możemy tworzyć zestawienia, które nie są znane w czasie kompilacji.
Rafael Winterhalter

Odpowiedzi:


54

Querydsl i jOOQ to dwie popularne opcje.


6
JOOQ jest być może lepszym wyborem do hardkorowego rozwoju SQL, ale Querydsl ma prostsze API i obsługuje także inne backendy (JPA, JDO, Lucene, Mongodb itp.); Jestem również w firmie stojącej za Querydsl
Timo Westkämper

Używamy Querydsl SQL w kilku naszych własnych projektach. Nie mam osobistych doświadczeń z jooq, ale słyszałem, że jest całkiem w porządku.
ponzao,

11
Problem z QueryDsl polega na tym, że nie możesz go używać jako czystego generatora zapytań, ponieważ nie dostarcza on samego wygenerowanego zapytania. Wygeneruje zapytanie i wykona je również za Ciebie. Nie możesz dostać jednego bez drugiego.
Abhinav Sarkar,

5
Querydsl i jOOQ wydają się być najpopularniejszymi i dojrzałymi opcjami, jednak należy pamiętać o jednej rzeczy: oba opierają się na koncepcji generowania kodu, w którym meta-klasy są generowane dla tabel i pól bazy danych. Ułatwia to ładne, czyste DSL, ale napotyka problem podczas próby tworzenia zapytań do baz danych, które są znane tylko w czasie wykonywania, jak w powyższym przykładzie OP. Podczas gdy jOOQ obsługuje podejście oparte na ciągach, istnieją pewne dziwactwa. Dokumentacja Querydsl nie wspomina o tym, czy można nie używać generowania kodu. Proszę popraw mnie jeżeli się mylę.
Sven Jacobs

3
@SvenJacobs bardzo stary komentarz, ale aby zaktualizować, QueryDSL pozwala na budowanie sql bez generowania kodu: stackoverflow.com/questions/21615956/ ...
Nagaraj Tantri

7

ddlutils to mój najlepszy wybór: http://db.apache.org/ddlutils/api/org/apache/ddlutils/platform/SqlBuilder.html

oto przykład tworzenia (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

1
Muszę ponownie zdefiniować kolumny, chociaż zdefiniowałem je już w @Entity, więc ból.
huuthang

6

Mogę polecić jOOQ . Zapewnia wiele wspaniałych funkcji, a także intuicyjny DSL dla SQL i niezwykle konfigurowalne podejście do inżynierii wstecznej.

jOOQ skutecznie łączy złożony SQL, bezpieczeństwo typów, generowanie kodu źródłowego, aktywne rekordy, procedury składowane, zaawansowane typy danych i Javę w płynny, intuicyjny DSL.


Czy używasz tego? Jak ty to znalazłeś?
Vladislav Rastrusny

3
Używam go do generowania niestandardowego kodu źródłowego z DDL. Działa świetnie!
Christopher Klewes,

„Chociaż biblioteka jOOQ ma świetne API do tworzenia instrukcji SQL, zawiera cały zestaw narzędzi do budowania instrukcji, łączenia się z bazami danych, zapisywania / odczytywania modeli do / z baz danych itp. Ze względu na obecny charakter aplikacji dla systemu Android VM , istnieje limit odwołań do metod 64k. jOOQ może zawierać ponad 10 000 metod, do których się odwołujemy, gdy jest w użyciu. To może nie wydawać się dużo w porównaniu z limitem, ale jeśli weźmiesz pod uwagę inne powszechnie używane duże biblioteki (takie jak Guava i usługi Google Play) , osiągnięcie tego limitu 64 KB staje się znacznie łatwiejsze ”. - android-arsenal.com/details/1/3202 :(
Tomáš Fejfar

3

Hibernate Criteria API (choć nie zwykły SQL, ale bardzo potężny i aktywnie rozwijany):

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
Problem polega na tym, że nie jest on mapowany na SQL, jak rozumiem, prawda?
Vladislav Rastrusny

7
to nie generuje SQL i jest koszmarem do debugowania, gdy nie działa zgodnie z zasadą najmniejszego zdziwienia (nie działa zgodnie z oczekiwaniami)

Generuje SQL (na końcu) i nikogo nie dziwi. Korzyści - można je przenosić między bazami danych.
Vladimir Dyuzhev

3
Jaki jest poziom złożoności zapytań, który osiągnąłeś dzięki API Kryteriów JPA, który nie sprawia, że ​​zapytanie jest całkowicie nieczytelne? Czy masz przykład zagnieżdżonego wyboru w klauzuli IN/ EXISTSlub samosprzężenia przy użyciu aliasów dla Saleencji itp.? Jestem ciekawy
Lukas Eder

1
Komentarze nie pozostawiają
Vladimir

0

Możesz skorzystać z następującej biblioteki:

https://github.com/pnowy/NativeCriteria

Biblioteka jest zbudowana na szczycie Hibernate „create sql query”, więc obsługuje wszystkie bazy danych obsługiwane przez Hibernate (obsługiwane są sesje Hibernate i dostawcy JPA). Dostępny jest wzorzec konstruktora i tak dalej (elementy odwzorowujące obiekty, elementy mapujące wyniki).

Przykłady można znaleźć na stronie github, biblioteka jest oczywiście dostępna w centrali 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")));

jest to bardziej skomplikowane niż ręczne
pisanie kodu

@EpicPandaForce Zgadzam się na bardzo proste przypadki, ale konkatenacja jest znacznie skomplikowana, gdy trzeba konkatenować ten ciąg w oparciu o bardzo skomplikowane warunki, w których występuje inny zestaw tych warunków. Prawidłowo połączony ciąg (podobnie jak wszystkie dodania, łączenia, ustawianie parametrów itp.) Jest uciążliwy. Dzięki rozwiązaniu masz konstruktora, który poradzi sobie z tą złożonością za Ciebie.
Przemek Nowak
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.