欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

如何解决hibernate duplicate association

程序员文章站 2022-03-06 15:29:45
...

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