it-swarm.it

Hibernate Query per esempio e proiezioni

Per farla breve: Hibernate non supporta le proiezioni e la query con l'esempio? Ho trovato questo post:

Il codice è questo:

User usr = new User();
usr.setCity = 'TEST';
getCurrentSession().createCriteria(User.class)
.setProjection( Projections.distinct( Projections.projectionList()
.add( Projections.property("name"), "name")
.add( Projections.property("city"), "city")))
.add( Example.create(usr))

Come ha detto l'altro poster, lo sql generato continua ad avere una classe in cui si fa riferimento solo a y0_ =? invece di this_.city

Ho già provato diversi approcci e ho cercato il tracker dei problemi ma non ho trovato nulla a riguardo.

Ho persino provato ad usare alias di Projection e Transformers, ma non funziona:

User usr = new User();
usr.setCity = 'TEST';
getCurrentSession().createCriteria(User.class)
.setProjection( Projections.distinct( Projections.projectionList()
.add( Projections.property("name"), "name")
.add( Projections.property("city"), "city")))
.add( Example.create(usr)).setResultTransformer(Transformers.aliasToBean(User.class));

Qualcuno ha usato proiezioni e query con l'esempio?

21
Miguel Ping

Posso vedere la tua classe utente? Questo è solo usando le restrizioni di seguito. Non vedo perché le restrizioni sarebbero davvero diverse dagli esempi (penso che i campi nulli vengano ignorati di default negli esempi).

getCurrentSession().createCriteria(User.class)
.setProjection( Projections.distinct( Projections.projectionList()
.add( Projections.property("name"), "name")
.add( Projections.property("city"), "city")))
.add( Restrictions.eq("city", "TEST")))
.setResultTransformer(Transformers.aliasToBean(User.class))
.list();

Non ho mai usato l'alaistToBean, ma ho appena letto su di esso. Potresti anche ripetere i risultati ..

List<Object> rows = criteria.list();
for(Object r: rows){
  Object[] row = (Object[]) r;
  Type t = ((<Type>) row[0]);
}

Se necessario, puoi compilare manualmente l'utente in questo modo.

È un po 'difficile da esaminare nel problema senza ulteriori informazioni per diagnosticare il problema.

16
Arthur Thomas

Il problema sembra verificarsi quando si ha un alias con lo stesso nome della proprietà objects. Hibernate sembra raccogliere l'alias e usarlo nella sql. Ho trovato questo documento qui e qui , e credo che sia un bug in Hibernate, anche se non sono sicuro che il team di Hibernate sia d'accordo.

Ad ogni modo, ho trovato un semplice lavoro che funziona nel mio caso. Il tuo chilometraggio può variare. I dettagli sono di seguito, ho provato a semplificare il codice per questo esempio, quindi mi scuso per eventuali errori o errori di battitura:

Criteria criteria = session.createCriteria(MyClass.class)
    .setProjection(Projections.projectionList()
        .add(Projections.property("sectionHeader"), "sectionHeader")
        .add(Projections.property("subSectionHeader"), "subSectionHeader")
        .add(Projections.property("sectionNumber"), "sectionNumber"))
    .add(Restrictions.ilike("sectionHeader", sectionHeaderVar)) // <- Problem!
    .setResultTransformer(Transformers.aliasToBean(MyDTO.class));

Produrrebbe questo sql:

select
    this_.SECTION_HEADER as y1_,
    this_.SUB_SECTION_HEADER as y2_,
    this_.SECTION_NUMBER as y3_,
from
    MY_TABLE this_ 
where
    ( lower(y1_) like ? ) 

Che stava causando un errore: Java.sql.SQLException: ORA-00904: "Y1_": identificatore non valido

Ma, quando ho cambiato la mia restrizione per usare "questo", in questo modo:

Criteria criteria = session.createCriteria(MyClass.class)
    .setProjection(Projections.projectionList()
        .add(Projections.property("sectionHeader"), "sectionHeader")
        .add(Projections.property("subSectionHeader"), "subSectionHeader")
        .add(Projections.property("sectionNumber"), "sectionNumber"))
    .add(Restrictions.ilike("this.sectionHeader", sectionHeaderVar)) // <- Problem Solved!
    .setResultTransformer(Transformers.aliasToBean(MyDTO.class));

Ha prodotto il seguente sql e il mio problema è stato risolto.

select
    this_.SECTION_HEADER as y1_,
    this_.SUB_SECTION_HEADER as y2_,
    this_.SECTION_NUMBER as y3_,
from
    MY_TABLE this_ 
where
    ( lower(this_.SECTION_HEADER) like ? ) 

Questo è tutto! Una soluzione piuttosto semplice per un problema doloroso. Non so come questa correzione possa tradursi nella query con il problema di esempio, ma potrebbe avvicinarti.

44
Ryan Cook

Il vero problema qui è che c'è un bug in ibernazione dove usa gli alias select-list nella clausola where:

http://opensource.atlassian.com/projects/hibernate/browse/HHH-817

Nel caso in cui qualcuno atterra qui in cerca di risposte, vai a dare un'occhiata al biglietto. Ci sono voluti 5 anni per risolvere il problema ma in teoria sarà in una delle prossime versioni e quindi sospetto che il tuo problema andrà via.

6
Dobes Vandermeer

Sto affrontando un problema simile. Sto usando Query per esempio e voglio ordinare i risultati per un campo personalizzato. In SQL vorrei fare qualcosa di simile:

select pageNo, abs(pageNo - 434) as diff
from relA
where year = 2009
order by diff

Funziona bene senza la clausola order-by-clausola. Quello che ho ottenuto è

Criteria crit = getSession().createCriteria(Entity.class);
crit.add(exampleObject);
ProjectionList pl = Projections.projectionList();
pl.add( Projections.property("id") );
pl.add(Projections.sqlProjection("abs(`pageNo`-"+pageNo+") as diff", new String[] {"diff"}, types ));
crit.setProjection(pl);

Ma quando aggiungo 

crit.addOrder(Order.asc("diff"));

Ottengo un org.hibernate.QueryException: impossibile risolvere la proprietà: diff exception. Anche la soluzione con this non funziona. 

PS: dato che non sono riuscito a trovare alcuna documentazione elaborata sull'uso di QBE per Hibernate, tutto il materiale sopra riportato è principalmente un approccio trial-and-error

0
VHristov
ProjectionList pl = Projections.projectionList();
pl.add(Projections.property("id"));
pl.add(Projections.sqlProjection("abs(`pageNo`-" + pageNo + ") as diff", new String[] {"diff"}, types ), diff); ---- solution
crit.addOrder(Order.asc("diff"));
crit.setProjection(pl);
0
singh