当前位置:首页 » PHP技术

如何解决hibernate duplicate association

2018-06-13 08:21 本站整理 浏览(55)

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