2008-09-11 18 views
7

Poszukuję konstruktora dla HQL w Javie. Chcę pozbyć się rzeczy, jak:Poszukuję konstruktora języka HQL (język zapytań Hibernuj)

StringBuilder builder = new StringBuilder() 
    .append("select stock from ") 
    .append(Stock.class.getName()) 
    .append(" as stock where stock.id = ") 
    .append(id); 

wolałbym mieć coś takiego:

HqlBuilder builder = new HqlBuilder() 
    .select("stock") 
    .from(Stock.class.getName()).as("stock") 
    .where("stock.id").equals(id); 

google trochę, a ja nie mogłem znaleźć.

Napisałem szybki & głupi & głupi , który odpowiada moim potrzebom na teraz, ale chciałbym znaleźć taki, który ma więcej użytkowników i testów niż ja sam.

Uwaga: Chciałbym, aby móc robić takie rzeczy i więcej, co nie udało mi się zrobić z API kryteria:

select stock 
from com.something.Stock as stock, com.something.Bonus as bonus 
where stock.someValue = bonus.id 

tj. wybierz wszystkie akcje, których własność someValue wskazuje na dowolną premię z tabeli Bonus.

Dzięki!

Odpowiedz

4

@Sébastien Rocca-Serra
Teraz jesteśmy już gdzieś beton. Tego rodzaju łączenie, które próbujesz wykonać, nie jest możliwe za pomocą interfejsu API Criteria, ale pod-zapytanie powinno wykonać to samo. Najpierw stwórz DetachedCriteria dla tabeli bonusowej, a następnie użyj operatora IN dla someValue.

DetachedCriteria bonuses = DetachedCriteria.forClass(Bonus.class); 
List stocks = session.createCriteria(Stock.class) 
    .add(Property.forName("someValue").in(bonuses)).list(); 

Jest to odpowiednik

select stock 
from com.something.Stock as stock 
where stock.someValue in (select bonus.id from com.something.Bonus as bonus) 

Jedynym minusem może być, jeśli mają odniesienia do różnych tabel w someValue i swój identyfikator użytkownika nie są unikalne na wszystkich stołach. Ale twoje zapytanie będzie cierpieć z powodu tej samej wady.

+0

Dzięki, to jest to, czego potrzebowałem. Dodałem rzut na pole id w pierwszym kryterium: bonuses.setProjection (Property.forName ("id")); Czy jest to wymagane/dobra praktyka/zła praktyka? Czemu ? Dzięki jeszcze raz. –

6

Czy to nie robi Criteria API? Wygląda prawie dokładnie tak, jak o to pytasz.

+0

Bingo. Działa doskonale dla mnie. –

4

Wygląda na to, że chcesz użyć interfejsu API zapytań Criteria wbudowanego w Hibernate. Aby wykonać powyższe zapytanie będzie wyglądać następująco:

List<Stock> stocks = session.createCriteria(Stock.class) 
    .add(Property.forName("id").eq(id)) 
    .list(); 

Jeśli nie masz dostępu do sesji hibernacji jeszcze można stosować „DetachedCriteria” tak:

DetachedCriteria criteria = DetachedCriteria.forClass(Stock.class) 
    .add(Property.forName("id").eq(id)); 

Jeśli chciał aby uzyskać wszystkie czas, które mają premię z określonym ID można wykonać następujące czynności:

DetachedCriteria criteria = DetachedCriteria.forClass(Stock.class) 
    .createCriteria("Stock") 
      .add(Property.forName("id").eq(id))); 

więcej infromation sprawdzeniu Criteria Queries z docs Hibernate

2

@Sébastien Rocca-Serra

select stock 
from com.something.Stock as stock, com.something.Bonus as bonus 
where stock.bonus.id = bonus.id 

to tylko przyłączyć. Hibernuj robi to automatycznie, jeśli i tylko wtedy, gdy masz mapowanie między konfiguracją Stock i Bonus, a jeśli bonus jest właściwością Stock. Criteria.list() zwróci obiekty Stock i po prostu zadzwonisz pod numer stock.getBonus().

Uwaga, jeśli chcesz zrobić coś podobnego

select stock 
from com.something.Stock as stock 
where stock.bonus.value > 1000000 

Trzeba użyć Criteria.createAlias(). Byłoby coś

session.createCriteria(Stock.class).createAlias("bonus", "b") 
    .add(Restrictions.gt("b.value", 1000000)).list() 
+0

Dzięki za odpowiedzi, zbliżam się! Ale staram się wybrać wszystkie akcje, których własność niektóre punkty wartości do dowolnego bonusu z tabeli Bonus ... –

2

Funkcja API kryteriów nie zapewnia wszystkich funkcji dostępnych w języku HQL. Na przykład nie można wykonać więcej niż jednego łączenia przez tę samą kolumnę.

Dlaczego nie używasz NAMED QUERIES? Wygląd znacznie bardziej czysty:

Person person = session.getNamedQuery("Person.findByName") 
          .setString(0, "Marcio") 
          .list(); 
2

Napisałem rozwiązanie GPL dla OMERO, które można łatwo zbudować w zależności od sytuacji.

Zastosowanie:

QueryBuilder qb = new QueryBuilder(); 
qb.select("img"); 
qb.from("Image", "img"); 
qb.join("img.pixels", "pix", true, false); 

// Can't join anymore after this 
qb.where(); // First 
qb.append("("); 
qb.and("pt.details.creationTime > :time"); 
qb.param("time", new Date()); 
qb.append(")"); 
qb.and("img.id in (:ids)"); 
qb.paramList("ids", new HashSet()); 
qb.order("img.id", true); 
qb.order("this.details.creationEvent.time", false); 

Funkcjonuje on jako machiny państwowej „Select-> od-> join-> where-> zamówienie ", itp. i utrzymuje się z opcjonalnymi parametrami. Było kilka zapytań, których API Criteria nie potrafił wykonać (patrz: HHH-879), więc na koniec prostsze było napisanie tej małej klasy do zawijania StringBuilder. (Uwaga: istnieje zgłoszenie HHH-2407 opisujące gałąź Hibernate, która powinna zunifikować te dwa.) Później prawdopodobnie ponowne odwiedzanie API Criteria)

+0

Interesujące, dzięki! –

2

Zapoznaj się z pakietem wyszukiwania dostępnym w projekcie hibernate-generic-dao . To całkiem przyzwoita implementacja HQL Builder.

2

Znam ten wątek jest dość stary, ale ja też szukałem HqlBuilder I znalazłem ten "screensaver" project
nie jest to wygaszacz ekranu systemu Windows, jest to "Lab systemu Information Management (LIMS) o wysokiej przepustowości obiekty przesiewowe (HTS), które wykonują ekrany małocząsteczkowe i RNAi "

Zawiera HQLBuilder, który wygląda całkiem nieźle.
Oto przykładowa lista dostępnych metod:

... 
HqlBuilder select(String alias); 
HqlBuilder select(String alias, String property); 
HqlBuilder from(Class<?> entityClass, String alias); 
HqlBuilder fromFetch(String joinAlias, String joinRelationship, String alias); 
HqlBuilder where(String alias, String property, Operator operator, Object value); 
HqlBuilder where(String alias, Operator operator, Object value); 
HqlBuilder where(String alias1, Operator operator, String alias2); 
HqlBuilder whereIn(String alias, String property, Set<?> values); 
HqlBuilder whereIn(String alias, Set<?> values); 
HqlBuilder where(Clause clause); 
HqlBuilder orderBy(String alias, String property); 
HqlBuilder orderBy(String alias, SortDirection sortDirection); 
HqlBuilder orderBy(String alias, String property, SortDirection sortDirection); 
String toHql(); 
... 
+0

Interesujące, dzięki! –

6

dla typu bezpieczne podejście do problemu, należy rozważyć Querydsl.

Przykład zapytania staje

HQLQuery query = new HibernateQuery(session); 
List<Stock> s = query.from(stock, bonus) 
    .where(stock.someValue.eq(bonus.id)) 
    .list(stock); 

Querydsl APT używa do generowania kodu jak JPA2 i wspiera JPA/Hibernate, JDO, SQL i kolekcje Java.

Jestem opiekunem Querydsl, więc ta odpowiedź jest stronnicza.

+0

Dzięki, popatrzę! –

5

Dla innego zapytania dsl typu bezpiecznego, polecam http://www.torpedoquery.org.Biblioteka jest jeszcze młoda, ale zapewnia bezpieczeństwo typu bezpośrednio poprzez zajęcia z twojej jednostki. Oznacza to wczesne błędy kompilatora, gdy zapytanie nie ma zastosowania przed refaktoryzacją lub przeprojektowaniem.

Podałem ci również przykład. Myślę, że z Twoich postów, które gdzie próbuje zrobić ograniczenie podzapytanie, więc oparł exemple na ten temat:

import static org.torpedoquery.jpa.Torpedo.*; 

Bonus bonus = from(Bonus.class); 
Query subQuery = select(bonus.getId()); 

Stock stock = from(Stock.class); 
where(stock.getSomeValue()).in(subQuery); 

List<Stock> stocks = select(stock).list(entityManager); 
0

Teraz dostępne są również średnia JPA Type Safe zapytanie i mniej standardowe, ale również dobre Object Query

Przykłady:

JPA Rodzaj Sejf

EntityManager em = ... 
CriteriaBuilder qb = em.getCriteriaBuilder(); 
CriteriaQuery<Stock> c = qb.createQuery(Stock.class); 
Root<Stock> = c.from(Stock.class); 
Predicate condition = qb.eq(p.get(Stock_.id), id); 
c.where(condition); 
TypedQuery<Stock> q = em.createQuery(c); 
List<Stock> result = q.getResultList(); 

Zapytanie Obiekt

EntityManager em = ... 
ObjectQuery<Stock> query = new GenericObjectQuery<Stock>(Stock.class); 
Stock toSearch = query.target(); 
query.eq(toSearch.getId(),id); 
List<Stock> res = (List<Stock>)JPAObjectQuery.execute(query, em); 
Powiązane problemy