优化Hibernate的SQLCriterion_支持同时多表别名

Criteria rootCr = session.createCriteria(entityClazz);
Criteria subACr = rootCr.createCriteria("subA","a");
Criteria subBCr = rootCr.createCriteria("subB","b");

String sql = "{alias}.root_time > date_add({a}.a_time, interval 20 hour or {b}.b_time > date_add({a}.a_time, interval 20 hour "

rootCr.add(Restrictions.sqlRestriction(sql));

 

注:date_add函数是MySQL的,无需理会

上面这段代码使用Hibernate3是会报错的,Hibernate只会将{alias}替换成加入了SQLCriterion的Criteria的别名,此处是rootCr,默认为this_,而对于{a}和{b}都无视。在生成的sql中subA和subB表的别名分别为a1_和b2_,所以会报错

 

修改SQLCriterion的实现可以达到多表别名替换的效果:

import java.util.Iterator;

import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.criterion.CriteriaQuery;
import org.hibernate.criterion.Criterion;
import org.hibernate.engine.TypedValue;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.impl.CriteriaImpl.Subcriteria;
import org.hibernate.type.Type;
import org.hibernate.util.StringHelper;

/**
 * Hack the original class
 * 2012-04-10
 * @author wangzhen
 * 
 */
public class SQLCriterion implements Criterion {
	private static final long	serialVersionUID	= 561456879784847643L;
	private final String sql;
	private final TypedValue[] typedValues;

	public String toSqlString(
		Criteria criteria,
		CriteriaQuery criteriaQuery)
	throws HibernateException {
		CriteriaImpl rootCriteria = null;
		if(criteria instanceof CriteriaImpl){
			rootCriteria = (CriteriaImpl)criteria;
		}else if(criteria instanceof Subcriteria){
			rootCriteria = (CriteriaImpl) ((Subcriteria)criteria).getParent();
		}else {
			throw new HibernateException("暂不支持其他Criteria的实现");
		}
		Iterator iterateSubcriteria = rootCriteria.iterateSubcriteria();
		String tempSql = sql;
		//replace subcriterias' alias
		while (iterateSubcriteria.hasNext()) {
			Subcriteria subCriteria = (Subcriteria) iterateSubcriteria.next();
			tempSql = StringHelper.replace( tempSql, "{"+subCriteria.getAlias()+"}", criteriaQuery.getSQLAlias(subCriteria) );
		}
		return StringHelper.replace( tempSql, "{alias}", criteriaQuery.getSQLAlias(criteria) );
	}

	public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
	throws HibernateException {
		return typedValues;
	}

	public String toString() {
		return sql;
	}

	public SQLCriterion(String sql, Object[] values, Type[] types) {
		this.sql = sql;
		typedValues = new TypedValue[values.length];
		for ( int i=0; i<typedValues.length; i++ ) {
			typedValues[i] = new TypedValue( types[i], values[i], EntityMode.POJO );
		}
	}
}
 

你可能感兴趣的:(Hibernate)