How do I return in json the foreign key in Spring Boot?

2

As you can see, he is returning cities without any problems at the following URL: http://localhost:8080/cidades , please note:

Thisisadirectreturnfromthedatabasewithselect*fromcidade,canyouseeanydifference?

Notethatinthestatus_codeattributeappearsintheSQLperformedinthedatabase,butthesameattributedoesnotappearinthelistmadebytheSpringBootJavaAPI,asIwouldalsoliketheattributewouldalsobereturnedinJavaAPIJson.

HowdoIgettheAPItoreturnthisattribute?

HerebelowarethecodesrespondingtothelistreturnedbytheURL:http://localhost:8080/cidades

Thecontroller:

packagecom.algaworks.brewer.resource;importjava.util.List;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importcom.algaworks.brewer.model.Cidade;importcom.algaworks.brewer.model.Estado;importcom.algaworks.brewer.repository.CidadeRepository;importcom.algaworks.brewer.repository.EstadoRepository;importcom.algaworks.brewer.repository.filter.CidadeFilter;@RestController@RequestMapping("/cidades")
public class CidadeResource {


    @Autowired
    private  CidadeRepository cidadeRepository;

    @Autowired
    private  EstadoRepository estadoRepository;


    @GetMapping
    public List<Cidade> pesquisarPorCidade(CidadeFilter cidadeFilter){
        return cidadeRepository.filtrar(cidadeFilter);
    }

    @GetMapping("/estados")
    public List<Estado> pesquisarPorEstado(){
        return estadoRepository.findAll();
    }


}

The repository :

package com.algaworks.brewer.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.algaworks.brewer.model.Cidade;
import com.algaworks.brewer.repository.cidade.CidadeRepositoryQuery;

public interface CidadeRepository extends JpaRepository<Cidade, Long> , CidadeRepositoryQuery {


}

The filter implementation interface:

package com.algaworks.brewer.repository.cidade;

import java.util.List;

import com.algaworks.brewer.model.Cidade;
import com.algaworks.brewer.repository.filter.CidadeFilter;

public interface CidadeRepositoryQuery {

        public List<Cidade> filtrar(CidadeFilter cidadeFilter);
}

The implementation itself:

package com.algaworks.brewer.repository.cidade;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.util.StringUtils;

import com.algaworks.brewer.model.Cidade;
import com.algaworks.brewer.model.Cidade_;
import com.algaworks.brewer.repository.filter.CidadeFilter;

public class CidadeRepositoryImpl implements CidadeRepositoryQuery {


    @PersistenceContext
    private EntityManager manager;

    @Override
    public List<Cidade> filtrar(CidadeFilter cidadeFilter) {
        CriteriaBuilder builder = manager.getCriteriaBuilder();
        CriteriaQuery<Cidade> criteria = builder.createQuery(Cidade.class);
        Root<Cidade> root = criteria.from(Cidade.class);

        Predicate[] predicates = criarRestricoes(cidadeFilter, builder, root);
        criteria.where(predicates);

        TypedQuery<Cidade> query = manager.createQuery(criteria);
        return query.getResultList();
    }


    private Predicate[] criarRestricoes(CidadeFilter cidadeFilter, CriteriaBuilder builder,
            Root<Cidade> root) {
        List<Predicate> predicates = new ArrayList<>();

        if (!StringUtils.isEmpty(cidadeFilter.getNome())) {
            predicates.add(builder.like(
                    builder.lower(root.get(Cidade_.nome)), "%" + cidadeFilter.getNome().toLowerCase() + "%"));
        }





        return predicates.toArray(new Predicate[predicates.size()]);
    }


}





//if (cidadeFilter.getEstado() != null) {
//  predicates.add(
//          builder.greaterThanOrEqualTo(root.get(Cidade_.estado.getName()), cidadeFilter.getEstado().getNome()));
//}

I'm looking forward to the return!

This is the city code:

package com.algaworks.brewer.model;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotBlank;

import com.fasterxml.jackson.annotation.JsonIgnore;

@Entity
@Table(name = "cidade")
public class Cidade implements Serializable  {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long codigo;

    @NotBlank(message = "Nome é obrigatório")
    private String nome;

    @NotNull(message = "Estado é obrigatório")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "codigo_estado")
    @JsonIgnore
    private Estado estado;

    public Long getCodigo() {
        return codigo;
    }

    public void setCodigo(Long codigo) {
        this.codigo = codigo;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public Estado getEstado() {
        return estado;
    }

    public void setEstado(Estado estado) {
        this.estado = estado;
    }

    public boolean temEstado() {
        return estado != null;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((codigo == null) ? 0 : codigo.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Cidade other = (Cidade) obj;
        if (codigo == null) {
            if (other.codigo != null)
                return false;
        } else if (!codigo.equals(other.codigo))
            return false;
        return true;
}
}

And from the entity State:

package com.algaworks.brewer.model;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "estado")
public class Estado implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long codigo;
    private String nome;
    private String sigla;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long getCodigo() {
        return codigo;
    }

    public void setCodigo(Long codigo) {
        this.codigo = codigo;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getSigla() {
        return sigla;
    }

    public void setSigla(String sigla) {
        this.sigla = sigla;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((codigo == null) ? 0 : codigo.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Estado other = (Estado) obj;
        if (codigo == null) {
            if (other.codigo != null)
                return false;
        } else if (!codigo.equals(other.codigo))
            return false;
        return true;
    }
}

You may notice that there is a @JsonIgnore in private Estado estado it's being ignored, I took that code from somewhere else that's why it's there, I need to make a changeover time so that LAZY still works.

see the excerpt:

@NotNull(message = "Estado é obrigatório")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "codigo_estado")
    @JsonIgnore
    private Estado estado;
    
asked by anonymous 02.02.2018 / 19:46

1 answer

2

@wladyband,

If I understood your problem well, you would like to display the status code next to the city data. In addition, you also want to keep @JsonIgnore in the @ManyToOne relationship with the State class, since you do not want to prevent all state objects from being converted and that all state data is in the city, but only your code.

OBS : As a matter of curiosity, since version 2.6 of the Jackson (library for processing Json, which is default in Spring MVC), we have a more intuitive annotation than @JsonIgnore , which is @JsonProperty and you can control access in more detail:

@JsonProperty(access = Access.WRITE_ONLY)
private String myField;

@JsonProperty(access = Access.WRITE_ONLY)
private String myField2;

@JsonProperty(access = Access.READ_WRITE)
private String myField3;

Take a closer look at documentation > of this note.

Within all of this I realized that you want to do, you will only have the option of creating a new attribute within the city class to contain only the state code, without performing @ManyToOne relationship, and not using any anotation to ignore to be serialized. In this field we will treat it so that it is not used to be inserted in the bank nor to update anything related in the database, that is, it will be a transient field or just for reading. Here's how it would look:

package com.algaworks.brewer.model;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotBlank;

import com.fasterxml.jackson.annotation.JsonIgnore;

@Entity
@Table(name = "cidade")
public class Cidade implements Serializable  {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long codigo;

    @NotBlank(message = "Nome é obrigatório")
    private String nome;

    @NotNull(message = "Estado é obrigatório")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "codigo_estado")
    @JsonIgnore
    private Estado estado;

    @Column(name="codigo_estado", updatable=false, insertable=false) 
    private Long codigoEstado;

    public Long getCodigo() {
        return codigo;
    }

    public void setCodigo(Long codigo) {
        this.codigo = codigo;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public Estado getEstado() {
        return estado;
    }

    public void setEstado(Estado estado) {
        this.estado = estado;
    }

    public boolean temEstado() {
        return estado != null;
    }

    public Long getCodigoEstado() {
        return codigoEstado;
    }

    public void setCodigoEstado(Long codigoEstado) {
        this.codigoEstado = codigoEstado;
    }

    //........
}

Anything, please let me know so you can try to improve the explanation. I do not know if I captured all your need and restriction.

    
03.02.2018 / 04:09