Join fetch multiple returning duplicate values JPA Criteria API

Asked

Viewed 346 times

1

In the method in question I want to return the consultation with the joins of employee and company. However, the Company class is related to the Query and the Employee, and is returning duplicate in JSON.

Query class

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

@Id
private long id;

@Column(name="IDEMPRESA")
private Long idEmpresa;

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="IDEMPRESA", referencedColumnName = "ID", 
insertable=false, updatable=false)
private Empresa empresa;

@Column(name="IDEMPREGADO")
private Long idEmpregado;

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
    @JoinColumn(name="IDEMPRESA", referencedColumnName="EMPRESA", insertable=false, updatable=false),
    @JoinColumn(name="IDEMPREGADO", referencedColumnName="ID", insertable=false, updatable=false)
})
private Empregado empregado;

/* Getters e Setter */
}

Business Class

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

@Id
private Long id;

@Column(name="CIDADE")
private Long idCidade;

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="CIDADE", referencedColumnName = "ID", insertable=false, updatable=false)
private Cidade cidade;

@Column(name="RAZAOSOCIAL")
private String razaoSocial;

private String denominacao;

private String cnpj;

private String ddd;

private String fone;

private Character status;

private Long usuario;

/* Getters e Setter */
}

Employee class

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

@EmbeddedId
private EmpregadoPK id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "EMPRESA", referencedColumnName = "ID", insertable = false, updatable = false)
private Empresa empresa;

private String nome;

/* Getters e Setters */

}

Method with the fetch

public Consulta getById(Long id) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Consulta> cq = cb.createQuery(Consulta.class);
    Root<Consulta> consulta = cq.from(Consulta.class);

    List<Predicate> predicates = new ArrayList<Predicate>();

    predicates.add(cb.equal(consulta.<Long>get("id"), id));

    cq.distinct(true);

    consulta.fetch("empresa");
    consulta.fetch("empregado");

    cq.select(consulta).where(predicates.toArray(new Predicate[]{}));

    TypedQuery<Consulta> tquery = em.createQuery(cq);
    tquery.setMaxResults(1);

    return tquery.getSingleResult();
}

JSON of return

{
"id": 1268,
"data": "2018-03-27",
"hora": "01/01/1970 09:00:00",
"descricao": null,
"idEmpresa": 1,
"empresa": {
    "id": 1,
    "razaoSocial": "Demonstração LTDA"
},
"idEmpregado": 45,
"empregado": {
    "id": {
        "idEmpresa": 1,
        "id": 45
    },
    "empresa": {
        "id": 1,
        "razaoSocial": "Demonstração LTDA"
    },
    "nome": " ANA MARIA COSTA PORTO",
    "admissao": "2017-09-13",
    "demissao": null,
    "nascimento": "1966-11-17",
    "sexo": "M",
    "matricula": "65989898"
},
"status": "1"
}
  • Include the JSON that is being returned, in order to facilitate the understanding of the scenario.

  • @Weslleytavares edited the question.

1 answer

0

The simplest way to avoid repetition of entity-related information Empresa (since I don’t know your data model) would use the resource @JsonIgnoreProperties in class Empregado, including the attribute empresa, as shown below:

@JsonIgnoreProperties(value = { "empresa" })
@Entity
@Table(name="EMPREGADOS")
public class Empregado implements Serializable {
    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private EmpregadoPK id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "EMPRESA", referencedColumnName = "ID", insertable = false, updatable = false)
    private Empresa empresa;

    private String nome;

    /* Getters e Setters */

}

It is possible to make use of the mechanism of ignoring an attribute of a class when suffering serialization for JSON in other ways (using @JsonIgnore, for example), but I prefer to use this way that was used in the example for ease of reading the code and also for future inclusions and/or deletions of attributes for JSON.

Now a question about your data model: what is the motivator of the class Consulta relate so much to Empregado as to Empresa? Note that only the relationship with the class Empregado would be enough to get all the information in your JSON.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.