Domanda

Cerco costruttore per HQL a Giava.Voglio sbarazzarmi di cose come:

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

Preferirei avere qualcosa del tipo:

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

Ho cercato un po' su Google e non sono riuscito a trovarne uno.

Ho scritto un veloce e stupido HqlBuilder che si adatta alle mie esigenze per ora, ma mi piacerebbe trovarne uno che abbia più utenti e test di me solo.

Nota:Mi piacerebbe essere in grado di fare cose come questa e altre, cosa che non sono riuscito a fare con l'API Criteria:

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

cioè.seleziona tutti i titoli la cui proprietà someValue punta a Qualunque bonus dalla tabella Bonus.

Grazie!

È stato utile?

Soluzione

@Sébastien Rocca-Serra
Ora stiamo ottenendo qualcosa di concreto.Il tipo di join che stai tentando di eseguire non è realmente possibile tramite l'API Criteria, ma una sottoquery dovrebbe ottenere lo stesso risultato.Per prima cosa crei un file DetachedCriteria per la tabella bonus, quindi utilizzare il file IN operatore per someValue.

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

Ciò equivale a

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

L'unico svantaggio sarebbe se nel file fossero presenti riferimenti a tabelle diverse someValue e i tuoi ID non sono univoci in tutte le tabelle.Ma la tua query soffrirebbe dello stesso difetto.

Altri suggerimenti

Il API dei criteri fallo per te stesso?Sembra quasi esattamente quello che stai chiedendo.

Per un approccio sicuro per i tipi al tuo problema, prendi in considerazione Querydsl.

La query di esempio diventa

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

Querydsl utilizza APT per la generazione di codice come JPA2 e supporta raccolte JPA/Hibernate, JDO, SQL e Java.

Sono il manutentore di Querydsl, quindi questa risposta è parziale.

Per un'altra query DSL indipendente dai tipi, lo consiglio http://www.torpedoquery.org.La libreria è ancora giovane ma fornisce l'indipendenza dai tipi utilizzando direttamente le classi della tua entità.Ciò significa errori precoci del compilatore quando la query non si applica più prima del refactoring o della riprogettazione.

Ti ho anche fornito un esempio.Penso dai tuoi post che stavi cercando di eseguire una restrizione della sottoquery, quindi ho basato l'esempio su questo:

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);

Sembra che tu voglia utilizzare l'API di query Criteria incorporata in Hibernate.Per fare la tua query sopra sarebbe simile a questa:

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

Se non hai ancora accesso alla sessione di ibernazione, puoi utilizzare 'DetachedCriteria' in questo modo:

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

Se volessi ottenere tutte le azioni che hanno un bonus con un ID specifico, potresti fare quanto segue:

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

Per ulteriori informazioni controlla Domande sui criteri dai documenti di Hibernate

@Sébastien Rocca-Serra

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

Questa è solo un'unione.Hibernate lo fa automaticamente, se e solo se hai la mappatura in mezzo Stock E Bonus configurazione e se bonus è una proprietà di Stock. Criteria.list() sarà di ritorno Stock oggetti e tu semplicemente chiami stock.getBonus().

Nota, se vuoi fare qualcosa del genere

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

Devi usare Criteria.createAlias().Sarebbe qualcosa del genere

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

L'API dei criteri non fornisce tutte le funzionalità disponibili in HQL.Ad esempio, non puoi eseguire più di un join sulla stessa colonna.

Perché non usi QUERY NOMINATE?L'aspetto è molto più pulito:

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

Ho scritto una soluzione GPL per OMERO che potresti facilmente creare adatta alla tua situazione.

Utilizzo:

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);

Funziona come una macchina a stati "seleziona->da->unisci->dove->ordina", ecc.e tiene il passo con i parametri opzionali.C'erano diverse query che l'API Criteria non poteva eseguire (vedi HHH-879), quindi alla fine è stato più semplice scrivere questa piccola classe per racchiudere StringBuilder.(Nota:c'è un biglietto HHH-2407 descrivendo un ramo Hibernate che dovrebbe unificare i due.Successivamente, probabilmente avrebbe senso visitare nuovamente l'API Criteria)

Dai un'occhiata al pacchetto di ricerca disponibile da hibernate-generico-dao progetto.Questa è un'implementazione di HQL Builder abbastanza decente.

So che questo thread è piuttosto vecchio, ma stavo anche cercando un HqlBuilder e ho trovato questo progetto "salvaschermo".
Non è un salvaschermo di Windows, è un "Lab Information Management System (LIMS) per strutture di screening ad alto rendimento (HTS) che eseguono screening di piccole molecole e RNAi."

Contiene un HQLBuilder che sembra abbastanza buono.
Ecco un elenco esemplificativo dei metodi disponibili:

...
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();
...

Ora sono disponibili anche quelle standard Tipo JPA sicuro query e meno standard ma anche buona Interrogazione oggetto

Esempi:

Tipo JPA sicuro

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();

Interrogazione oggetto

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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top