我們使用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;
}
}