Op soek na 'n HQL bouer (Hibernate Query Language)
Vra
Ek is op soek na 'n bouer vir HQL in Java. Ek wil om ontslae te raak van dinge soos:
StringBuilder builder = new StringBuilder()
.append("select stock from ")
.append( Stock.class.getName() )
.append( " as stock where stock.id = ")
.append( id );
Ek wil eerder iets soos:
HqlBuilder builder = new HqlBuilder()
.select( "stock" )
.from( Stock.class.getName() ).as( "stock" )
.where( "stock.id" ).equals( id );
Ek googled 'n bietjie, en ek kon nie een vind.
Ek het 'n vinnige en stom HqlBuilder
wat pas by my behoeftes vir nou, maar ek sou graag wou een wat meer gebruikers en toetse alleen as my vind.
Let wel: Ek wil graag in staat wees om dinge te doen soos hierdie en nog baie meer, wat ek versuim het om te doen met die kriteria API:
select stock
from com.something.Stock as stock, com.something.Bonus as bonus
where stock.someValue = bonus.id
ie. Kies alle aandele waarvan die eiendom someValue
punte na enige bonus van die Bonus tafel.
Dankie!
Oplossing
@ Sébastien Rocca-Serra
Nou is ons om iewers beton. Die soort van aan te sluit jy probeer om te doen is nie regtig moontlik deur die kriteria API, maar 'n sub-navraag moet dieselfde ding te bewerkstellig. Eerste 'n DetachedCriteria
vir die bonus tafel skep jy, gebruik dan die IN
operateur vir someValue
.
DetachedCriteria bonuses = DetachedCriteria.forClass(Bonus.class);
List stocks = session.createCriteria(Stock.class)
.add(Property.forName("someValue").in(bonuses)).list();
Dit is gelykstaande aan
select stock
from com.something.Stock as stock
where stock.someValue in (select bonus.id from com.something.Bonus as bonus)
Die enigste nadeel sou wees as jy verwysings na verskillende tafels in someValue
en jou ID's is nie uniek in alle tafels. Maar jou navraag sou ly aan dieselfde fout.
Ander wenke
Maak nie die Kriteria API doen dit vir jou? Dit lyk amper presies soos wat jy vra vir.
Vir 'n tipe-veilige benadering tot jou probleem, oorweeg Querydsl .
Die voorbeeld navraag word
HQLQuery query = new HibernateQuery(session);
List<Stock> s = query.from(stock, bonus)
.where(stock.someValue.eq(bonus.id))
.list(stock);
Querydsl gebruik APT vir kodegenerasie soos JPA2 en ondersteun JPA / Hibernate, JDO, SQL en Java versamelings.
Ek is die onderhouer van Querydsl, so hierdie antwoord is bevooroordeeld.
Vir 'n ander tipe-veilige navraag dsl, Ek beveel aan http://www.torpedoquery.org . Die biblioteek is nog jonk, maar dit bied tipe veiligheid deur direk met behulp van klasse jou entiteit. Dit beteken vroeë samesteller foute wanneer die navraag nie meer van toepassing is voor van refactoring of herontwerp.
Ek julle het ook saam met 'n voorbeeld. Ek dink van jou poste wat jy waar probeer om 'n subquery beperking doen, so ek op grond van die exemple op dat:
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);
Dit lyk asof jy wil hê dat die kriteria navraag API gebou in Hibernate gebruik. Om jou bo navraag doen dit sou lyk:
List<Stock> stocks = session.createCriteria(Stock.class)
.add(Property.forName("id").eq(id))
.list();
As jy toegang tot die Hibernate Sessie nog nie het nie, kan jy gebruik 'DetachedCriteria' soos so:
DetachedCriteria criteria = DetachedCriteria.forClass(Stock.class)
.add(Property.forName("id").eq(id));
As jy wil al Stock dat 'n Bonus met 'n spesifieke ID kan jy die volgende doen het kry:
DetachedCriteria criteria = DetachedCriteria.forClass(Stock.class)
.createCriteria("Stock")
.add(Property.forName("id").eq(id)));
Vir meer inligting bevat check Kriteria Navrae van die Hibernate docs
select stock
from com.something.Stock as stock, com.something.Bonus as bonus
where stock.bonus.id = bonus.id
Dit is net 'n aan te sluit. Hibernate doen dit outomaties, as en slegs as jy die kartering tussen Stock
en Bonus
opstel en indien het bonus
is 'n eienskap van Stock
. Criteria.list()
sal Stock
voorwerpe terugkeer en jy net stock.getBonus()
noem.
Let wel, as jy wil om iets te doen soos
select stock
from com.something.Stock as stock
where stock.bonus.value > 1000000
Jy moet gebruik Criteria.createAlias()
. Dit sou so iets wees
session.createCriteria(Stock.class).createAlias("bonus", "b")
.add(Restrictions.gt("b.value", 1000000)).list()
Kriteria API verskaf nie al die funksies avaiable in HQL. Byvoorbeeld, kan jy nie meer as een aan te sluit oor dieselfde kolom doen.
Hoekom het jy nie gebruik NAAM NAVRAE ? Die voorkoms veel meer skoon:
Person person = session.getNamedQuery("Person.findByName")
.setString(0, "Marcio")
.list();
Ek het 'n GPL'd oplossing vir OMERO wat jy maklik geskik is vir jou situasie kan bou.
- Bron: QueryBuilder.java
- Toets: QueryBuilderMockTest
Gebruik:
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);
Dit funksioneer as 'n toestand masjien "Kies-> uit-> join-> waar-> orde", ens en tred hou met opsionele parameters. Daar was 'n hele paar navrae wat die kriteria API nie kan voer (sien HHH-879 'n>), so op die ou end is dit makliker was om hierdie klein klas te draai StringBuilder skryf. (Let wel: daar is 'n kaartjie HHH-2407 beskrywing van 'n Hibernate tak wat die twee moet verenig. Daarna sal dit waarskynlik sin maak om weer na die kriteria API)
Neem 'n blik op die search pakket beskikbaar vanaf die hiberneer-generiese-dao 'n> projek. Dit is 'n redelik ordentlike HQL Bouwer implementering.
Ek weet hierdie draad is redelik oud, maar ek is ook op soek na 'n HqlBuilder En ek het gevind dat hierdie " "projek screensaver
Dit is NIE 'n Windows screensaver, dit is 'n
" Lab Information Management System (LIMS) vir hoë deurset screening (HTS) fasiliteite wat klein molekule en RNAi skerms uit te voer. "
Dit bevat 'n HQLBuilder wat op soek is redelik goed.
Hier is 'n voorbeeld lys van beskikbare metodes:
...
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();
...
Nou is ook beskikbaar die standaard navraag JPA Tipe Veilige en 'n minder standaard, maar ook 'n goeie Object Query
Voorbeelde:
JPA Tipe Veilige
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();
Object Query
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);