Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

JPA ManyToMany resultados repetidos

Olá, tenho uma classe Médico que possui uma lista de outra classe Especialidade. Apenas o médico conhece sua especialidade. Relacionamento ManyToMany portanto o Hibernate faz a tb de relacionamento Medico_Especialidade com os ids fk das duas tabelas. ok Ele consegue salvar no persist etc. Porem quando vou buscar, seja usando o modo "FetchType.Eager" ou mesmo usando o Lazy... a lista de especialidades de cada médico vem quadruplicada com a mesma especialidade sendo que no banco está tudo correto. Alguem tem alguma experiência com esse problema? Já tentei usar query jpql de tudo que é jeito com distinct, left join etc como o curso abordou mas continua o mesmo problema. Alguem pode dar uma luz?

5 respostas

Imprimo a lista de especialidades de um médico e o hibernate faz isto quando faço por FetchType.Eager: Hibernate:

Hibernate: 
    select
        medico0_.id as id1_2_0_,
        medico0_.crm as crm2_2_0_,
        medico0_.enderecoMedico as endereco3_2_0_,
        medico0_.nomeMedico as nomeMedi4_2_0_,
        medico0_.telefoneMedico as telefone5_2_0_,
        especialid1_.Medico_id as Medico_i1_3_1_,
        especialid2_.id as especial2_3_1_,
        especialid2_.id as id1_1_2_,
        especialid2_.descricao as descrica2_1_2_,
        especialid2_.nome as nome3_1_2_ 
    from
        Medico medico0_ 
    left outer join
        Medico_Especialidade especialid1_ 
            on medico0_.id=especialid1_.Medico_id 
    left outer join
        Especialidade especialid2_ 
            on especialid1_.especialidades_id=especialid2_.id 
    where
        medico0_.id=?
[CLÍNICA MÉDICA, CLÍNICA MÉDICA, CLÍNICA MÉDICA, CLÍNICA MÉDICA]

No banco está tudo corretinho.

solução!

Oi Alex,

Deixe o relacionamento como LAZY(default) mesmo:

@Entity
public class Medico {

    @ManyToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE})
    @JoinTable(joinColumns = @JoinColumn(name = "medico_id"),inverseJoinColumns = @JoinColumn(name = "especialidade_id"))
    private List<Especialidade> especialidades = new ArrayList<>();
}

E tenta executar essa consulta via JPQL assim:

String jpql = "SELECT DISTINCT(m) FROM Medico m LEFT JOIN FETCH m.especialidades WHERE m.id = :id";
Medico medico = manager
.createQuery(jpql, Medico.class)
.setParameter("id", id)
.getSingleResult();

Veja se resolve.

Obrigado pela resposta. Fiz como disse:

    public static void main(String[] args) {

        String jpql = "SELECT DISTINCT(m) FROM Medico m LEFT JOIN FETCH m.especialidades WHERE m.id = :id";
        Medico medico = new FabricaEntity().getEntityManager()
        .createQuery(jpql, Medico.class)
        .setParameter("id", 1)
        .getSingleResult();

        System.out.println(medico.getEspecialidade());

[CLÍNICA MÉDICA, CLÍNICA MÉDICA, CLÍNICA MÉDICA, CLÍNICA MÉDICA] O resultado da list de especialidade continua sendo 4x quando só há um registro de CLINICA MÉDICA no banco e apenas uma associação na tabela relacionamento entre medico e especialidade.

Oi Alex,

Poste aqui o código das suas classes Medico e Especialidade, para analisarmos se tem algo de errado nos mapeamentos.

Olá, muito obrigado por seu pronto empenho em ajudar.

O Hibernate estava fazendo vários joins por qualquer caminho seja anotação fetch.eager na coluna, seja query seja acessando o atributo da lista antes de fechar o Entity... No banco parecia tudo em ordem(uso o Workbench para ver melhor até... mas dei o drop no schema e deixei ele reerguer( sem nem mexer no mapeamento) e passou a funcionar tudo normal. Eu configuro o Hibernate para erguer o schema sozinho caso não exista...

Eu não entendi o que houve. Agora ele faz apenas um join como deve e traz tudo certo. Acho que é mais um caso que pode servir a alguém que porventura tenha problema parecido sem causa aparente. Mais uma vez muito agradecido pela sua ajuda, Rodrigo.