Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding duplicates in result list with JPA

I have a problem with Groups containing GroupElements.

For example, with this data :

  • Group A contains elements 1,2,3
  • Group B contains elements 4,5,6

I try to list the Group and expect to get 2 Group with 3 GroupElement in each Group.

Instead, each Group is duplicated. I actually obtain 6 Group:

  • Group A contains elements 1,2,3
  • Group A contains elements 1,2,3
  • Group A contains elements 1,2,3
  • Group B contains elements 4,5,6
  • Group B contains elements 4,5,6
  • Group B contains elements 4,5,6

My guess is that a Group is rebuilt for each GroupElement.

I searched on SO and found that the problem could come from the equals()/hashCode() definition or from the way the request is written so I give you both.

I have this mapping :

@Entity
@Table(name = "xxx")
public class Group {

  ...

  @JsonBackReference
  @OneToMany(mappedBy = "group")
  private List<GroupElement> groupElements = Lists.newArrayList();

  //Getters & Setters

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }

    if (o == null || !o.getClass().equals(getClass())) {
      return false;
    }

   return getId() != null && getId().equals(((HasId) o).getId());
  }

  @Override
  public int hashCode() {
    return getId() != null ? getId().hashCode() : super.hashCode();
  }
}

I request groups like this :

public List<Group> listFull() {
  CriteriaBuilder cb = em.getCriteriaBuilder();
  CriteriaQuery<Group> query = cb.createQuery(Group.class);
  Root<Group> group = query.from(Group.class);
  group.fetch(Group_.groupElements, JoinType.LEFT);
  return em.createQuery(query).getResultList();
}

I can fix it with an intermediate Set but I ask this question in order to find a better solution.

like image 312
Arnaud Denoyelle Avatar asked Jan 29 '26 18:01

Arnaud Denoyelle


1 Answers

Set ResultTransformer to you (Hibernate)Criteria and you will get result without duplicates:

Session session = getSession();
Criteria criteria = session.createCriteria(clazz);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

If you are using JPA, try this:

CriteriaQuery<Group> query = cb.createQuery(Group.class);
query.distinct(true);
like image 129
dieter Avatar answered Jan 31 '26 08:01

dieter