web-dev-qa-db-fra.com

Requête Hibernate Par Exemple et Projections

Pour faire court: hibernate ne supporte pas les projections et requête par exemple? J'ai trouvé ce post:

Le code est le suivant:

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

Comme l’a dit l’autre affiche, le sql généré continue d’avoir une classe where qui se réfère à y0_ =? au lieu de this_.city

J'ai déjà essayé plusieurs approches et cherché dans l'outil de suivi des problèmes, mais rien trouvé à ce sujet.

J'ai même essayé d'utiliser l'alias de projection et Transformers, mais cela ne fonctionne pas:

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

Quelqu'un at-il utilisé des projections et des requêtes par exemple?

21
Miguel Ping

Puis-je voir votre classe d'utilisateurs? Ceci est juste en utilisant des restrictions ci-dessous. Je ne vois pas pourquoi les restrictions seraient vraiment différentes des exemples (je pense cependant que les champs nuls sont ignorés par défaut).

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

Je n'ai jamais utilisé alaistToBean, mais je viens de lire à ce sujet. Vous pouvez également simplement parcourir les résultats.

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

Si vous le devez, vous pouvez renseigner manuellement l'utilisateur vous-même de cette façon.

C'est un peu difficile de se pencher sur le problème sans disposer de plus d'informations pour le diagnostiquer.

16
Arthur Thomas

Le problème semble se produire lorsque vous avez un alias du même nom que la propriété objects. Hibernate semble prendre le pseudonyme et l'utiliser dans le sql. J'ai trouvé cela documenté ici et ici , et je pense que c'est un bug d'Hibernate, bien que je ne sois pas sûr que l'équipe d'Hibernate soit d'accord.

Quoi qu'il en soit, j'ai trouvé un moyen simple de contourner le problème. Votre kilométrage peut varier. Les détails sont ci-dessous, j'ai essayé de simplifier le code pour cet exemple, donc je m'excuse pour les erreurs ou les fautes de frappe:

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

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

Qui provoquait une erreur: Java.sql.SQLException: ORA-00904: "Y1_": identificateur non valide

Mais, quand j'ai changé ma restriction pour utiliser "this", comme ceci:

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

Il a produit le sql suivant et mon problème a été résolu.

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

C'est tout! Une solution assez simple à un problème douloureux. Je ne sais pas comment ce correctif se traduirait par un problème de requête par exemple, mais cela pourrait vous rapprocher.

44
Ryan Cook

Le vrai problème ici est qu’il ya un bogue dans hibernate qui utilise des alias de liste de sélection dans la clause where:

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

Juste au cas où quelqu'un atterrirait ici à la recherche de réponses, allez voir le billet. Cela a pris 5 ans pour résoudre le problème, mais en théorie ce sera dans l'une des prochaines versions et ensuite, je suppose que votre problème disparaîtra.

6
Dobes Vandermeer

Je suis confronté à un problème similaire. J'utilise une requête par exemple et je souhaite trier les résultats selon un champ personnalisé. En SQL je ferais quelque chose comme:

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

Cela fonctionne très bien sans ordre par clause. Ce que j'ai

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

Mais quand j'ajoute 

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

Je reçois un org.hibernate.QueryException: impossible de résoudre la propriété: diff exception. Solution de contournement avec this ne fonctionne pas non plus. 

PS: comme je ne trouvais aucune documentation détaillée sur l’utilisation de QBE pour Hibernate, tout ce qui est décrit ci-dessus est principalement une approche empirique.

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