1

Introduction

I have a legacy code that im having to give maintenance. I Have a code that loads all the child entities from a document entity. It loads fine, however, in the 'one to many' relationship ("revisoes") it brings duplicated records. I've attempted to use distinct but it didnt solve it.


Description of the problem

I have a class named Documento that has several child entities. All the entities are ManyToMany except for 'revisoes' which is oneToMany. The code below loads all the entities but 'revisoes' has duplicated records.

How do I solve it in such manner that "revisoes" doesnt bring duplicated records?


Code

@Entity
@Table(name = "documentos")
public class Documento extends Model {

    @NotFound(action = NotFoundAction.IGNORE)
    @ManyToOne(fetch = FetchType.EAGER)
    private TipoDeDocumento tipoDeDocumento;

    @Column(length = 250, nullable = false, unique = true)
    private String codigo;

    @NotFound(action = NotFoundAction.IGNORE)
    @ManyToMany(fetch = FetchType.EAGER)
    private Set<QuesitosNormas> quesitosNormas;

    @ManyToMany(fetch = FetchType.LAZY)
    private Set<PontoDeDistribuicao> pontosDistribuicao;

    @ManyToMany(fetch = FetchType.LAZY)
    private Set<Processo> processos;

    @Cascade(org.hibernate.annotations.CascadeType.ALL)
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "documento")
    private Collection<DocumentoRevisao> revisoes;

  @Override
    public Documento find(Long id, Session session, boolean closeSession) {
        try {
            CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
            
            CriteriaQuery<Documento> criteriaQuery = criteriaBuilder.createQuery(Documento.class);
      
            Root<Documento> rootDocument = criteriaQuery.from(Documento.class);
            rootDocument.fetch("quesitosNormas", JoinType.LEFT); // ManyToMany
            rootDocument.fetch("pontosDistribuicao", JoinType.LEFT); // ManyToMany
            rootDocument.fetch("processos", JoinType.LEFT); // ManyToMany
            rootDocument.fetch("tipoDeDocumento",JoinType.LEFT); //OneToOne
            rootDocument.fetch("revisoes", JoinType.LEFT); // OneToMany
            //
            //
            criteriaQuery.select(rootDocument);
            criteriaQuery.where(criteriaBuilder.equal(rootDocument.get("id"), id));
            criteriaQuery.distinct(true);

            Query<Documento> query = session.createQuery(criteriaQuery);
           
            Documento singleResult = query.getSingleResult();

            return singleResult;

        } catch (Exception ex) {
            throw ex;
        } finally {
            if (session != null && closeSession) {
                session.close();
            }
        }
    }

References

Hibernate Criteria fetches duplicates - one to many association

hibernate OneToMany criteria returns duplicates

Duplicated results in Hibernate OneToMany List

https://davidecerbo.medium.com/one-to-many-relationship-gets-duplicate-objects-without-using-any-tricks-a55012611539

KenobiBastila
  • 539
  • 4
  • 16
  • 52
  • did you consider changing revisoes to a Set i.e. `private Set revisoes` and override equals method in DocumentoRevisao if not done already? – jeet427 Feb 28 '23 at 08:13

1 Answers1

0
  1. try this -

    criteriaQuery.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
    --criteriaQuery.distinct(true);
    
  2. Instead of a Collection,

    @Cascade(org.hibernate.annotations.CascadeType.ALL)
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "document")
    private Collection<DocumentoRevisao> revisoes;
    

you can use Set, like this

@Cascade(org.hibernate.annotations.CascadeType.ALL)
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "documento")
private Set<DocumentoRevisao> revisoes;