it-swarm-eu.dev

Abfrage im Ruhezustand nach Beispiel und Projektionen

Um es kurz zu machen: Hibernate unterstützt keine Projektionen und Beispielabfragen? Ich habe diesen Beitrag gefunden:

Der Code lautet:

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

Wie auf dem anderen Poster gesagt: Die generierte SQL hat immer eine Where-Klasse, die sich nur auf y0_ =? anstelle von this_.city

Ich habe bereits mehrere Ansätze ausprobiert und den Issue Tracker durchsucht, aber nichts darüber gefunden.

Ich habe sogar versucht, Projektionsalias und Transformatoren zu verwenden, aber es funktioniert nicht:

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

Hat jemand Projektionen und Abfragen von Beispiel verwendet?

21
Miguel Ping

Kann ich Ihre Benutzerklasse sehen? Hier werden nur die folgenden Einschränkungen verwendet. Ich verstehe nicht, warum Einschränkungen sich wirklich von den Beispielen unterscheiden würden (ich denke jedoch, dass Nullfelder in den Beispielen standardmäßig ignoriert werden).

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

Ich habe den alaistToBean noch nie benutzt, aber ich habe nur darüber gelesen. Sie können auch einfach die Ergebnisse durchlaufen.

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

Wenn Sie müssen, können Sie den Benutzer auf diese Weise manuell ausfüllen.

Es ist schwer, sich mit dem Problem auseinanderzusetzen, ohne weitere Informationen zur Diagnose des Problems.

16
Arthur Thomas

Das Problem scheint zu bestehen, wenn Sie einen Alias ​​haben, der denselben Namen wie die Objekteigenschaft hat. Hibernate scheint den Alias ​​aufzuheben und in der SQL zu verwenden. Ich fand das dokumentiert hier und hier und glaube, dass es ein Fehler in Hibernate ist, obwohl ich nicht sicher bin, ob das Hibernate-Team zustimmt.

Auf jeden Fall habe ich eine einfache Arbeit gefunden, die in meinem Fall funktioniert. Ihre Laufleistung kann variieren. Die Details sind unten. Ich habe versucht, den Code für dieses Beispiel zu vereinfachen. Ich entschuldige mich für etwaige Fehler oder Tippfehler:

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

Würde diese SQL produzieren:

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

Was zu einem Fehler geführt hat: Java.sql.SQLException: ORA-00904: "Y1_": Ungültiger Bezeichner

Aber wenn ich meine Einschränkung geändert habe, um "this" zu verwenden, so:

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

Es erzeugte die folgende SQL und mein Problem wurde gelöst.

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

Das ist es! Eine ziemlich einfache Lösung für ein schmerzhaftes Problem. Ich weiß nicht, wie dieser Fix durch ein Beispielproblem in die Abfrage übersetzt werden würde, aber es könnte Ihnen näher kommen.

44
Ryan Cook

Das eigentliche Problem hier ist, dass es einen Fehler im Ruhezustand gibt, bei dem Auswahllisten-Aliasnamen in der where-Klausel verwendet werden:

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

Für den Fall, dass jemand hier auf der Suche nach Antworten landet, schauen Sie sich das Ticket an. Es hat fünf Jahre gedauert, um das Problem zu beheben, aber theoretisch wird es in einem der nächsten Releases sein.

6

Ich habe ein ähnliches Problem. Ich verwende Query by Example und möchte die Ergebnisse nach einem benutzerdefinierten Feld sortieren. In SQL würde ich so etwas tun:

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

Es funktioniert gut ohne die order-by-Klausel. Was ich habe ist

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

Aber wenn ich hinzufüge 

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

Ich bekomme eine org.hibernate.QueryException: Eigenschaft: diff exception konnte nicht aufgelöst werden. Problemumgehung mit this funktioniert auch nicht. 

PS: Da ich keine ausführliche Dokumentation zur Verwendung von QBE für Hibernate finden konnte, handelt es sich bei dem gesamten oben genannten Teil hauptsächlich um den Versuch und den Fehler

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