我们使用hibernate作为DAO层时,有时会遇到如下错误:
org.hibernate.QueryException: duplicate association path: agent
duplicate association
具体是什么错误呢?
Criteria criteria=this.inspectionOrderDao.createCriteria();
criteria.createCriteria("agent").add(Restrictions.eq("type", 1));//不报错
criteria.createCriteria("agent").add(Restrictions.eq("enable", 1));//报错:duplicate association
上面的代码就会报错.
实际代码结构及业务肯定比上述要复杂,
即设置条件不在一个方法里面.
如果出现这种异常就会直接导致接口报错,导致服务不可用.
如何解决 呢?
实际上我们有办法判断 Criteria 中是否已经存在了子查询路径:
public static SubCriteriaDto isSubcriteriaContains(Criteria criteria, String associationPath) {
CriteriaImpl criteria2 = (CriteriaImpl) criteria;
return isSubcriteriaContains(criteria2, associationPath);
}
/***
* 解决org.hibernate.QueryException: duplicate association path: community
* @param criteria2
* @param associationPath
* @return
*/
public static SubCriteriaDto isSubcriteriaContains(CriteriaImpl criteria2, String associationPath) {
Iterator<CriteriaImpl.Subcriteria> subcriteriaIterator = criteria2.iterateSubcriteria();
SubCriteriaDto subCriteriaDto=new SubCriteriaDto();
while (subcriteriaIterator.hasNext()) {
CriteriaImpl.Subcriteria subcriteria = subcriteriaIterator.next();
String path = subcriteria.getPath();
System.out.println("path :" + path);
if (path.equals(associationPath)) {
subCriteriaDto.setContains(true);
subCriteriaDto.setSubCriteria(subcriteria);
return subCriteriaDto;
}
}
return subCriteriaDto;
}
应用:
public void condition(Field field, Object entityProp) {
Integer id = ReflectHWUtils.getObjectIntValue(entityProp, Constant2.DB_ID);
if (null == id || id == SystemHWUtil.NEGATIVE_ONE) {
//解决Caused by: org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of oa.entity.HouseInfo.address
//没有执行createAssiate()
// criteria.createCriteria(key).add(getExample(value, false, isLike));
String associationPath = field.getName();
SubCriteriaDto subCriteriaDto=ConditionQueryUtil.isSubcriteriaContains(this.criteria, associationPath);
if (subCriteriaDto.isContains()) {//已经存在该路径的子查询
subCriteriaDto.getSubCriteria().add(Example.create(entityProp));
} else {
this.criteria.createCriteria(associationPath).add(Example.create(entityProp));
}
} else {
eq(field.getName() + ".id", id);
}
}
附上SubCriteriaDto结构:
package oa.bean;
import org.hibernate.internal.CriteriaImpl;
public class SubCriteriaDto {
private boolean isContains;
private CriteriaImpl.Subcriteria subCriteria;
public boolean isContains() {
return isContains;
}
public SubCriteriaDto setContains(boolean contains) {
isContains = contains;
return this;
}
public CriteriaImpl.Subcriteria getSubCriteria() {
return subCriteria;
}
public SubCriteriaDto setSubCriteria(CriteriaImpl.Subcriteria subCriteria) {
this.subCriteria = subCriteria;
return this;
}
}