使用hql或条件查询解决一对多关联查询的N+1查询问题

  如下两个实体类有一对多和多对一的双向关联
public class DictType
{
	@Id
	private int id;
	private String className;
	private String classDesc;
	@Column(name="isSys")
	private boolean sysParam;
	@OneToMany(cascade=CascadeType.MERGE,mappedBy="dictType",fetch=FetchType.LAZY)
	private Set parameters=new HashSet();

      //getter and setter...

}
@Entity
public class Parameter implements java.io.Serializable {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer id;
	private String parameterName;
	private String parameterValue;
	private String parameterDesc;
	@ManyToOne
	@JoinColumn(name="dictType")
	private DictType dictType;
//getter and setter...
}

现在要查询DictType 的同时关联查询出它下面的parameters。在集合延迟查询的情况下一次性出结果避免N+1问题(有关hibernate的N+1查询问题请自行百度)

使用hql解决:

String hqlString="select distinct d from DictType d left join fetch d.parameters";

注意这里的关键是left join 加了fetch,使得在延迟的情况下强制抓取关联。而加distinct是因为使用的是left join语句,如果一个DictType的parameters有多条数据那就会有多条DictType返回。

使用条件查询:
使用条件查询同样我们要解决延迟情况下关联集合的抓取和重复结果的筛选问题,以下代码使用的离线集合:

DetachedCriteria criteria=DetachedCriteria.forClass(clazz);
		criteria.setFetchMode("parameters", FetchMode.JOIN)
		.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
这里使用setFetchMode抓取关联集合,使用setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY)筛选重复结果。需要注意的是:
Criteria通过setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)方法对查询后结果进行排重,这种方式是先查询出可能重复的记录然后根据每个对象的equals方法进行排重,所以: 
  • 1. 要排重的对象要实现equals方法。
  • 2. 不能进行分页处理,因为是先查询后distinct,结果会不准确。
  • 3. 查询处理的结果集太大的话,可能存在性能问题,相同记录会查询多次;


你可能感兴趣的:(Java,hibernate)