0

I am trying to return a list of Hibernate entities from a list of ids. The following piece of code is responsible:

String sql = "select id from foo where some condition is met";
List<Long> ids = jdbcTemplate.queryForList(sql, Long.class); // 3 ids ..
List<FooEntity> list =  ((Session) this.entityManager.getDelegate())
        .createCriteria(FooEntity.class)
        .add(Restrictions.in("id", ids)).list(); // .. -> 60 entities

...

@Entity
public class FooEntity implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private long id;

  @OneToMany(
    targetEntity = BarEntity.class,
    cascade = { CascadeType.ALL },
    fetch = FetchType.EAGER)
  @JoinTable(
    name = "foo_bar",
    joinColumns = @JoinColumn(name = "foo_id"),
    inverseJoinColumns = @JoinColumn(name = "bar_id"))
  private List<BarEntity> bars;

  ...
}

When the code has executed I have a list of 3 ids and a list of 60 FooEntity instances!

Under normal circumstances I expect these lines of code to deliver just as many entities as ids. Any ideas what could cause this strange behaviour?

EDIT: Reacting to Thomas' comment below I found out that there are exactly 20 Bar instances for each Foo entity. And every FooEntity is also returned 20-fold.

achingfingers
  • 1,827
  • 5
  • 24
  • 48
  • 1
    Can you post the relevant part of `FooEntity`? Are the ids really unique? Are there any eager collections in `FooEntity` that are loaded via joins? – Thomas Jul 10 '14 at 15:40
  • 1
    How many bars do those 3 entities have? If I'd have to guess, there are 60 bars (or there are more eager joins in the model). – Thomas Jul 10 '14 at 15:46
  • @Thomas You are totally right. Every Foo has 20 Bars. No there are no mor eager joins. – achingfingers Jul 10 '14 at 15:48

2 Answers2

1

AFAIK Hibernate by default doesn't remove duplicates from the result lists unless you place a distinct(foo) in the query. Thus you'll get 60 entries in the list for 3 FooEntity instances which are joined with 20 BarEntity instances each, just because the JDBC result set will have 60 rows.

So add a distinct predicate to the query (have a look here: How to get distinct results in hibernate with joins and row-based limiting (paging)?) or use new LinkedHashSet<FooEntity>( list ) if FooEntity has a meaningful implementation of equals() and hashCode() (I'd not rely on the default implementation since in some situations Hibernate might create multiple instances of the same entity, which results in a "this breaks == semantics" message).

Community
  • 1
  • 1
Thomas
  • 87,414
  • 12
  • 119
  • 157
1

I'm using

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

to remove duplicates from Result

alex
  • 8,904
  • 6
  • 49
  • 75