Ainda não tem acesso? Estude com a gente! Matricule-se
Ainda não tem acesso? Estude com a gente! Matricule-se

Solucionado (ver solução)

Relacionamento @OnetoMany não funciona o LAZY

Olá!

Estou desenvolvendo uma API usando Spring Boot.

Defini o seguinte relacionamento entre as classes Vaga e Candidato.

Classe Vaga

@Entity
public class Vaga {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name="cargo", nullable = false, length = 50)
    private String cargo;

    @Column(name="descricao", nullable = false, length = 100)
    private String descricao;

    @Temporal(TemporalType.DATE)
    @Column(name="dt_vencimento")
    private Calendar dataVencimento;

    @OneToMany(mappedBy = "vaga", fetch = FetchType.LAZY)
    private List<Candidato> candidatos;    

Classe Candidato

@Entity
public class Candidato {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name="cpf", nullable = false, length = 11)
    private String cpf;

    @Column(name="nome", nullable = false, length = 100)
    private String nome;

    @Column(name="telefone", nullable = false, length = 11)
    private String telefone;

    @ManyToOne(fetch = FetchType.LAZY)
    private Vaga vaga;

Ao chamar a API o resultado é isso, mesmo colocando fetchType.LAZY

parte do Json ....

[
    {
        "id": 1,
        "cargo": "programador",
        "descricao": "programador",
        "dataVencimento": "2020-05-01T03:00:00.000+0000",
        "candidatos": [
            {
                "id": 1,
                "cpf": "11111111111",
                "nome": "tiago",
                "telefone": "11111111111",
                "vaga": {
                    "id": 1,
                    "cargo": "programador",
                    "descricao": "programador",
                    "dataVencimento": "2020-05-01T03:00:00.000+0000",
                    "candidatos": [
                        {
                            "id": 1,
                            "cpf": "11111111111",
                            "nome": "tiago",
                            "telefone": "11111111111",
                            "vaga": {
                                "id": 1,
                                "cargo": "programador",
                                "descricao": "programador",
                                "dataVencimento": "2020-05-01T03:00:00.000+0000",
                                "candidatos": [
                                    {
                                        "id": 1,
                                        "cpf": "11111111111",
                                        "nome": "tiago",
                                        "telefone": "11111111111",
                                        "vaga": {

O que devo fazer????? Independente se consulto por vaga ou por candidato retorna esse json quase infinito....

Eu gostaria de :

  • listar todos os candidatos por vaga
  • listar candidato e mostrar os dados da vaga conforme o relacionamento biredicional feitos na classe utilizando JPA.
3 respostas

Oi Tiago,

Isso deve estar acontecendo porque provavelmente você deve estar devolvendo do seu controller a entidade diretamente, ao invés de um DTO.

E nesse caso o Spring ao serializar a entidade Vaga encontra o atributo Candidatos, forçando assim um novo select para carregar a lista de candidatos, pois a lista é lazy e ainda não foi carregada.

Eu criaria 3 DTOs para resolver esse problema:

public class VagaDto {

    private Integer id;
    private String cargo;
    private String descricao;

    //getters, setters, construtor
}
public class CandidatoDto {

    private Integer id;
    private String nome;
    private String cpf;

    //getters, setters, construtor
}
public class CandidatosPorVagaDto {

    private VagaDto vaga;
    private List<CandidatoDto> candidatos;

    //getters, setters, construtor
}

E a consulta no repository:

public interface CandidatoRepository extends JpaRepository<Candidato, Integer> {

    List<Candidato> findByVaga(Vaga vaga);

}

Desse jeito resolve o problema do json infinito por conta do relacionamento bidirecional.

Bons estudos!

Legal! Pesquisando para tentar solucionar esse problema encontrei sobre DTO mas não entendi muito bem.

Esse DTO seria a classe que representa a interface de entrada e saida de uma requisição? Nesse caso eu não preciso usar a @Entity para retornar as informações é isso mesmo ?

Obrigado

solução

Oi Tiago, isso mesmo!

DTO é uma classe Java simples, sem anotações e sem depender de nenhum framework, utilizada apenas para representar os dados que chegam e que saem da API.