Hibernate, select traz resultados de 2 tabelas

4 respostas
E

Olá pessoal, tenho o seguinte caso:
Meu modelo Trilha tenho a seguinte anotação

@JoinColumn(name = "triEmpresa", referencedColumnName = "idEmpresa", insertable = false, updatable = false)
    @ManyToOne(optional = false)
    private Empresa empresa;

Meu TrilhaDAO , tenho o seguinte select:

@SuppressWarnings("unchecked")
    public List<Trilha> toXML() {
        System.out.println("Iniciou");
        Query query = manager.createQuery("select t FROM Trilha t", Trilha.class);

        return query.getResultList();
    }

Meu resultado é esse:

<trilhas>
   <trilha>
   <empresa>
      <empNome>DLOGICA</empNome>
      <empVideo>Aqui vem o vídeo</empVideo>
      <idEmpresa>4</idEmpresa>
   </empresa>
   <triAula>0</triAula>
   <triCurso>0</triCurso>
   <triDesc>Finanças</triDesc>
   <triDescr>Curso de Finanças</triDescr>
   <trilhaPK>
      <idTrilha>1</idTrilha>
      <triEmpresa>4</triEmpresa>
   </trilhaPK>
</trilha>

Minha dúvida é a seguinte toda vez que eu executo o select para o resultado o hibernate executa 2 selects e eu queria apenas o select de Trilha, como posso fazer isso ?
Se eu remover o @ManyToOne funciona mas acho que não deva ser o correto, alguma alternativa, abaixo a query executada no hibernate !

Hibernate: 
    select
        trilha0_.idTrilha as idTrilha1_9_,
        trilha0_.triEmpresa as triEmpre2_9_,
        trilha0_.triAula as triAula3_9_,
        trilha0_.triCurso as triCurso4_9_,
        trilha0_.triDesc as triDesc5_9_,
        trilha0_.triDescr as triDescr6_9_,
        trilha0_.triDtcad as triDtcad7_9_,
        trilha0_.triImagem as triImage8_9_,
        trilha0_.triTipo as triTipo9_9_,
        trilha0_.triTrilha as triTril10_9_ 
    from
        Trilha trilha0_
Hibernate: 
    select
        empresa0_.idEmpresa as idEmpres1_2_0_,
        empresa0_.empNome as empNome2_2_0_,
        empresa0_.empVideo as empVideo3_2_0_ 
    from
        Empresa empresa0_ 
    where
        empresa0_.idEmpresa=?

4 Respostas

Lucas_Camara

Penso que o correto seria retirar o optional da anotação e fazer o join quando necessário na consulta JPQL.

C

Não tenho muita experências, mas acredito que seja o “problema” N+1 do hibernate.
Quando se tem um relacionamento ManyToOne ou ManyToMany, pra cada select, ele faz +1.
Uma forma de evitar isso é usar a anotação @ManyToOne(fetch = FetchType.LAZY), assim ele só carregara a sua classe Trilha.

E

Grato pelos esclarecimentos

Mas o fetch não funcionou como nosso combinado

@JoinColumn(name = triEmpresa, referencedColumnName = idEmpresa, insertable = false, updatable = false)

@ManyToOne(optional = false, fetch=FetchType.LAZY)

private Empresa empresa;
Então resolvi da seguinte forma

Criteria crit = session.createCriteria(Trilha.class);

crit.setProjection(Projections.projectionList()

.add(Projections.property(trilhaPK).as(trilhaPK))

.add(Projections.property(triDesc).as(triDesc))

.add(Projections.property(triDescr).as(triDescr))

.add(Projections.property(triAula).as(triAula))

.add(Projections.property(triCurso).as(triCurso))

.add(Projections.property(triTrilha).as(triTrilha))

.add(Projections.property(triImagem).as(triImagem))

.add(Projections.property(triTipo).as(triTipo))

.add(Projections.property(triDtcad).as(triDtcad))

);
if ((tr == 0) && (cu == 0)) { //para trazer somente as trilhas
        crit.add(Restrictions.eq("triCurso", new Short("0")));
    } else if (al != 0) { //para trazer somente a aula
        crit.add(Restrictions.eq("triAula", al));
        crit.add(Restrictions.eq("triTipo", "A"));
        crit.add(Restrictions.eq("triCurso", cu));
        crit.add(Restrictions.eq("triTrilha", tr));
    } else if (cu != 0) { //para trazer todas as aulas do curso
        crit.add(Restrictions.eq("triCurso", cu));
        crit.add(Restrictions.eq("triTipo", "A"));
        crit.add(Restrictions.eq("triTrilha", tr));
    } else if (tr != 0) { //para trazer todos os cursos da trilha
        crit.add(Restrictions.eq("triTrilha", tr));
        crit.add(Restrictions.eq("triTipo", "C"));
    }
    crit.setResultTransformer(new AliasToBeanResultTransformer(Trilha.class));
    List list = crit.list();
C

Acredito que não tenha funcionado por causa do “optional=true”. Nesse caso você coloca a associação como mandatória. Tenta assim:

@ManyToOne(fetch=FetchType.LAZY)

Criado 22 de janeiro de 2016
Ultima resposta 2 de fev. de 2016
Respostas 4
Participantes 3