hibernate的一个BUG

BUG简单描述:在Criteria联表查询中,Hibernate装组出无效的SQL。
版本:3.25GA,在最新版3.50rc2上BUG存在那个类中未发现有更改。


    下面是简单的示例代码:

    两个类:某类(FlexLink)和组织类(Organization),关系为多对一。

//创建查询器
		DetachedCriteria c = DetachedCriteria.forClass(FlexLink.class, "_link");
		//再创建一个子属性别名
		c.createAlias("_link.organization", "organization");
		//子属性的条件
		c.add(Restrictions.eq("organization.orgName", "xxx"));
		//只查部份属性
		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.property("organization.orgName").as("organization.orgName"));
		c.setProjection(projectionList);
		//调用SPRING提供的DAO查询
		flexLinkDAO.getHibernateTemplate().findByCriteria(c);
		
		//生成的SQL:
		select
        	organizati1_.ORGANIZATION_NAME as y0_ 
	    from
	        BIS_FLEX_LINK this_ 
	    inner join
	        SYS_ORGANIZATION organizati1_ 
	            on this_.ORGANIZATION_ID=organizati1_.ORGANIZATION_ID 
	    where
	        y0_=?//问题就出在这里,这里可以用organizati1_.ORGANIZATION_NAME=?,但不能用y0_这个别名


    上面的SQL在ORACLE和MYSQL上都是不能执行的,y0_这别名不能用作条件关键字,但是可以用在order by 名子中,如order by y0_。
     那么是哪个类出错了?最直观看到的就是CriteriaQueryTranslator类的getColumnsUsingProjection方法:

/**
	 * Get the names of the columns constrained
	 * by this criterion.
	 * 此方法在criteria查中,把查询对象翻译成SQL时要用到,
	 * 用于取得JAVA属性名对应的SQL的字段名或SQL别名
	 * 在这里,getWhereCondition调用此方法组装where条件
	 */
	public String[] getColumnsUsingProjection(
			Criteria subcriteria,
	        String propertyName) throws HibernateException {

		//first look for a reference to a projection alias
		final Projection projection = rootCriteria.getProjection();
		//就是这一行有问题,就是这里返回了y0_这个别名,这里也不全错,上面说是order by y0_是可以的,
		//Hibernate组装order by 句子的时也要调用此方法,
		String[] projectionColumns = projection == null ?
		                             null :
		                             projection.getColumnAliases( propertyName, 0 );

		if ( projectionColumns == null ) {
			//it does not refer to an alias of a projection,
			//look for a property
			try {
				return getColumns( propertyName, subcriteria );
			}
			catch ( HibernateException he ) {
				//not found in inner query , try the outer query
				if ( outerQueryTranslator != null ) {
					return outerQueryTranslator.getColumnsUsingProjection( subcriteria, propertyName );
				}
				else {
					throw he;
				}
			}
		}
		else {
			//it refers to an alias of a projection
			return projectionColumns;
		}
	}


    改BUG方案:

     方案一,改源码:就把那行有问题的直接改成String[] projectionColumns = null就可以,或者直接保留try catch块就可以了,不影响。
     方案二,避免此问题:此问题的根本原因在于select句中为orgName这个字段建立了别名,所以在组装条件句时才取到别名,那如果select句中不查orgName这个字段就不会有这个问题。

    如果有更好的解决方法,欢迎讨论。

你可能感兴趣的:(spring,oracle,sql,Hibernate,Flex)