Resolvendo N+1 com join fetch

Boa tarde galera,
Estou com problemas de N+1 e estou tentando resolve-lo com join fetch, porém quando tenho mais de um relacionamento venho tendo problemas…

Minhas tabelas são da seguinte forma:

Visita AS visi
-visi.visi_id
-visi.vis_id

Visitante AS vis
-vis.vis_id
-vis.cid_id

Cidade AS cid
-cid.cid_id
-cid.est_id

Estado AS est
-est.est_id

Acho que deu pra entender como estão minhas tabelas…
O que eu tentei foi o seguinte:

O erro que eu obtive foi:

Como eu faria o join fetch com mais de um relacionamento e não ter n+1 querys?

Obrigado desde já!
Abraço!

Mapeamentos:

Visita:
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "visi_id")
    private long visi_id;
    @ManyToOne
    @JoinColumn(name="vis_id", nullable = false) 
    private Visitante vis_id;
    @Column(name = "visi_entrada", columnDefinition = "DATETIME", nullable=false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date visi_entrada;
    @Column(name = "visi_saida", columnDefinition = "DATETIME", nullable=true)
    @Temporal(TemporalType.TIMESTAMP)
    private Date visi_saida;
    @Column(name = "visi_motivo")
    private String visi_motivo;

Visitante:
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "vis_id")
    private long vis_id;
    @Column(name = "vis_nome", nullable = false)
    private String vis_nome;
    @Column(name = "vis_digital", columnDefinition = "LONGBLOB")
    @Basic(fetch = FetchType.LAZY)
    private byte[] vis_digital;
    @Column(name = "vis_empresa")
    private String vis_empresa;
    @Column(name = "vis_empresacnpj")
    private String vis_empresacnpj;
    @ManyToOne
    @JoinColumn(name = "cid_id")
    private Cidade cid_id;

Cidade:
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cid_id")
    private long cid_id;
    @Column(name = "cid_nome", nullable=false)
    private String cid_nome;
    @JoinColumn(name="est_id", nullable = false) 
    @ManyToOne(cascade=CascadeType.PERSIST)
    private Estado est_id;

Estado:
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "est_id")
    private long est_id;
    @Column(name = "est_nome", nullable=false)
    private String est_nome;
    @Column(name = "est_sigla", unique=true, nullable=false)
    private String est_sigla;

Qual informação você quer trazer?

No caso seria todos Visita.

Consegui entender como funciona…
Obrigado pela atenção!

O problema que estou agora, é que não é obrigatorio ter cid_id, então algumas vezes ele é NULL então perderei dado.
Então com JOIN FETCH só será mostrado caso exista dados nos dois relacionamentos, correto?
Como eu faria pra mostrar o dado, e caso não exista o relacionamento, o objeto fique como NULL.

Por exemplo, meu código ficou assim:

No caso, as vezes v1.cid_id será NULL, e percebi que dessa forma eu perco os dados que v1.cid_id é NULL, como ficaria pra eu não perder esse dado?

Obrigado novamente!
Abraço!

utilize o left join…

Aqui mostra como utilizar e outras dicas: JPA Consultas e Dicas.

[quote=Hebert Coelho]utilize o left join…

Aqui mostra como utilizar e outras dicas: JPA Consultas e Dicas.[/quote]
Isso mesmo, obrigado pela dica!

Me deparei com outro problema que procurei em seu site e não achei, veja se vc consegue me ajudar.
Eu tenho a seguinte anotação:

@OneToMany(mappedBy = "vis_id", fetch = FetchType.LAZY) @Where(clause = "tel_tipo_dado = 1") @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE) private List<Telefone> telefone; @OneToMany(mappedBy = "vis_id", fetch = FetchType.LAZY) @Where(clause = "tel_tipo_dado = 2") @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE) private List<Telefone> telefoneEmp;

Nesse caso eu vou conseguir fazer um LEFT JOIN FETCH?
Eu tentei com: LEFT JOIN FETCH vis.telefone AS t1 LEFT JOIN FETCH vis.telefoneEmp AS t2
E me deparei com o erro Hibernate cannot simultaneously fetch multiple bags
Li um pouco sobre e ainda não entendi pq acontece e como acertar…

Abraço!
Até mais! Abraço!

[quote=faelzindc]Nesse caso eu vou conseguir fazer um LEFT JOIN FETCH?
Eu tentei com: LEFT JOIN FETCH vis.telefone AS t1 LEFT JOIN FETCH vis.telefoneEmp AS t2
E me deparei com o erro Hibernate cannot simultaneously fetch multiple bags
Li um pouco sobre e ainda não entendi pq acontece e como acertar…[/quote]
Aqui fala sobre isso: JPA: Mini Livro - Primeiros passos e conceitos detalhados.

[quote=Hebert Coelho][quote=faelzindc]Nesse caso eu vou conseguir fazer um LEFT JOIN FETCH?
Eu tentei com: LEFT JOIN FETCH vis.telefone AS t1 LEFT JOIN FETCH vis.telefoneEmp AS t2
E me deparei com o erro Hibernate cannot simultaneously fetch multiple bags
Li um pouco sobre e ainda não entendi pq acontece e como acertar…[/quote]
Aqui fala sobre isso: JPA: Mini Livro - Primeiros passos e conceitos detalhados.[/quote]

Perfeito!

Você é o mestre!

Valeu!

Tenha uma boa tarde.
Abraço e até mais!