Criteria API: Fetch of a list returns repeated main entity

孤者浪人 提交于 2019-11-30 09:31:37
  1. There is a difference between eager loading and fetch join. Eager loading doesn't mean that the data is loaded within the same query. It just means that it is loaded immediately, although by additional queries.

  2. The criteria is always translated to an SQL query. If you specify joins, it will be join in SQL. By the nature of SQL, this multiplies the data of the root entity as well, which leads to the effect you got. (Note that you get the same instance multiple times, so the root entity is not multiplied in memory.)

There are several solutions to that:

  • use distinct(true)
  • Use the distinct root entity transformer (.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)).
  • When you don't need to filter by child properties, avoid the join
  • When you need to filter by child properties, filter by a subquery (DetachedCriteria).
  • Optimize the N+1 problem by using batch-size

Have you tried calling distinct(true) on the CriteriaQuery?

The JPA 2 specification, page 161, says:

The DISTINCT keyword is used to specify that duplicate values must be eliminated from the query result.

If DISTINCT is not specified, duplicate values are not eliminated.

The javadoc also says:

Specify whether duplicate query results will be eliminated.A true value will cause duplicates to be eliminated. A false value will cause duplicates to be retained. If distinct has not been specified, duplicate results must be retained.

The reason why you don't need the distinct when the association is eagerly loaded is probably just that the association is not loaded using a fetch join, but using an additional query.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!