it-swarm-pt.tech

Consulta de Hibernação por exemplo e projeções

Para resumir: o hibernate não suporta projeções e consulta por exemplo? Eu encontrei este post:

O código é este:

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

Como o outro pôster disse, o sql gerado continua tendo uma classe onde se referir apenas a y0_ =? em vez de this_.city

Eu já tentei várias abordagens e pesquisei o rastreador de problemas, mas não encontrei nada sobre isso.

Eu até tentei usar o alias de projeção e Transformers, mas não funciona:

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

Alguém já usou projeções e consulta por exemplo?

21
Miguel Ping

Posso ver sua classe de usuário? Isso é apenas usando as restrições abaixo. Não vejo por que as Restrições seriam realmente diferentes de Exemplos (acho que os campos nulos são ignorados por padrão nos exemplos).

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

Eu nunca usei o alaistToBean, mas acabei de ler sobre isso. Você também pode passar por cima dos resultados.

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

Se precisar, você pode preencher manualmente o usuário dessa maneira.

É difícil analisar o problema sem mais algumas informações para diagnosticar o problema.

16
Arthur Thomas

O problema parece acontecer quando você tem um alias com o mesmo nome da propriedade de objetos. O Hibernate parece pegar o alias e usá-lo no sql. Eu achei isso documentado aqui e aqui , e acredito que seja um bug no Hibernate, embora eu não tenha certeza se a equipe do Hibernate concorda.

De qualquer maneira, eu encontrei um trabalho simples que funciona no meu caso. Sua milhagem pode variar. Os detalhes estão abaixo, tentei simplificar o código para este exemplo, por isso peço desculpas por quaisquer erros ou erros de digitação:

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

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

O que estava causando um erro: Java.sql.SQLException: ORA-00904: "Y1_": identificador inválido

Mas, quando mudei minha restrição para usar "this", assim:

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

Produziu o seguinte sql e meu problema foi resolvido.

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

É isso aí! Uma solução simples para um problema doloroso. Não sei como essa correção se traduziria na consulta por problema de exemplo, mas isso pode aproximá-lo.

44
Ryan Cook

O problema real aqui é que há um bug no hibernate onde ele usa aliases de lista de seleção na cláusula where:

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

Apenas para o caso de alguém chegar aqui procurando respostas, veja o ingresso. Levou 5 anos para ser consertado, mas em teoria ele estará em um dos próximos lançamentos e então eu suspeito que o seu problema irá embora.

6
Dobes Vandermeer

Estou enfrentando um problema semelhante. Estou usando a consulta por exemplo e quero classificar os resultados por um campo personalizado. No SQL eu faria algo como:

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

Funciona bem sem a ordem por cláusula. O que eu tenho é

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

Mas quando eu adiciono 

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

Eu recebo um org.hibernate.QueryException: não pude resolver a propriedade: diff exception. Solução alternativa com this também não funciona. 

PS: como não consegui encontrar nenhuma documentação elaborada sobre o uso de QBE para o Hibernate, todas as coisas acima são principalmente abordagem de tentativa e erro

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