Hibernate的querybuilder

Hibernate的querybuilder

package net.esj.basic.dao.querybuilder;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.esj.basic.exception.MelonException;
import net.esj.basic.expression.formula.Formula;
import net.esj.basic.utils.Validators;
import net.esj.basic.utils.hibe.AndCriteria;
import net.esj.basic.utils.hibe.HiCriteria;
import net.esj.basic.utils.hibe.OrCriteria;
import net.esj.basic.utils.hibe.SymbolExpression;

import org.hibernate.FetchMode;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.util.Assert;

public class HibernateQueryBuilder<T> implements QueryBuilder<T>, Serializable,
		Cloneable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -2175149119127080340L;

	private DetachedCriteria root = null;

	private Map<String, DetachedCriteria> subCri = new HashMap<String, DetachedCriteria>();

	private Class<T> clazz = null;
	
	private List<HiCriteria> hiCriterias = new ArrayList<HiCriteria>();

	private HibernateQueryBuilder(Class<T> clazz) {
		this.clazz = clazz;
		root = DetachedCriteria.forClass(clazz);
	}

	@Override
	public HibernateQueryBuilder<T> clone() {
		HibernateQueryBuilder<T> qb = null;
		try {
			qb = (HibernateQueryBuilder<T>) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return qb;
	}

	@Override
	public QueryBuilder<T> addCriterion(Criterion criterion) {
		root.add(criterion);
		return this;
	}

	@Override
	public QueryBuilder<T> allEq(Map propertyNameValues) {
		Assert.notNull(propertyNameValues, "传值不能为空!");
		root.add(Restrictions.allEq(propertyNameValues));
		return this;
	}

	@Override
	public QueryBuilder<T> between(String propertyName, Object lo, Object hi) {
		Assert.notNull(lo, "传值不能为空!");
		Assert.notNull(hi, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.between(propertyName, lo, hi));
		return this;
	}

	@Override
	public QueryBuilder<T> eq(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.eq(cri.getPropertyName(), value));
		return this;
	}

	@Override
	public QueryBuilder<T> ge(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.ge(cri.getPropertyName(), value));
		return this;
	}

	@Override
	public DetachedCriteria getDetachedCriteria() {
		return root;
	}

	@Override
	public QueryBuilder<T> gt(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.gt(cri.getPropertyName(), value));
		return this;
	}

	@Override
	public QueryBuilder<T> ilike(String propertyName, String value,
			MatchMode matchMode) {
		Assert.notNull(value, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(
				Restrictions.ilike(cri.getPropertyName(), value, matchMode));
		return this;
	}

	@Override
	public QueryBuilder<T> ilike(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.ilike(cri.getPropertyName(), value));
		return this;
	}

	@Override
	public QueryBuilder<T> in(String propertyName, Object[] values) {
		Assert.notNull(values, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.in(cri.getPropertyName(), values));
		return this;
	}

	@Override
	public QueryBuilder<T> in(String propertyName, Collection<T> values) {
		Assert.notNull(values, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.in(cri.getPropertyName(), values));
		return this;
	}

	@Override
	public QueryBuilder<T> isNotNull(String propertyName) {
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.isNotNull(cri.getPropertyName()));
		return this;
	}

	@Override
	public QueryBuilder<T> isNull(String propertyName) {
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.isNull(cri.getPropertyName()));
		return this;
	}

	@Override
	public QueryBuilder<T> le(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.le(cri.getPropertyName(), value));
		return this;
	}

	@Override
	public QueryBuilder<T> like(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.like(cri.getPropertyName(), value));
		return this;
	}

	@Override
	public QueryBuilder<T> like(String propertyName, String value,
			MatchMode matchMode) {
		Assert.notNull(value, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(
				Restrictions.like(cri.getPropertyName(), value, matchMode));
		return this;
	}

	@Override
	public QueryBuilder<T> lt(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.lt(cri.getPropertyName(), value));
		return this;
	}

	@Override
	public QueryBuilder<T> notEq(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空!");
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().add(Restrictions.ne(cri.getPropertyName(), value));
		return this;
	}

	@Override
	public QueryBuilder<T> leProperty(String propertyName,
			String otherPropertyName) {
		root.add(Restrictions.leProperty(propertyName, otherPropertyName));
		return this;
	}

	@Override
	public QueryBuilder<T> ltProperty(String propertyName,
			String otherPropertyName) {
		root.add(Restrictions.ltProperty(propertyName, otherPropertyName));
		return this;
	}

	@Override
	public QueryBuilder<T> eqProperty(String propertyName,
			String otherPropertyName) {
		root.add(Restrictions.eqProperty(propertyName, otherPropertyName));
		return this;
	}

	@Override
	public Class<T> getClazz() {
		return clazz;
	}

	@Override
	public QueryBuilder<T> OrderByAsc(String propertyName) {
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().addOrder(Order.asc(cri.getPropertyName()));
		return this;
	}

	@Override
	public QueryBuilder<T> OrderByDesc(String propertyName) {
		CriEntity cri = seekCriteria(propertyName,this);
		cri.getCri().addOrder(Order.desc(cri.getPropertyName()));
		return this;
	}
	
	@Override
	public QueryBuilder<T> fetch(String propertyTable, FetchMode fetchMode) {
		CriEntity entity = seekCriteria(propertyTable,this);
		entity.getCri().setFetchMode(entity.getPropertyName(), fetchMode);
		return this;
	}
	
	//TODO in test
	public QueryBuilder<T> hi(String propertyTable,HiCriteria hi){
		DetachedCriteria c =  createSub(propertyTable,this);
		c.add(hi.getCriterion());
		return this;
	}
	
	@Override
	public QueryBuilder<T> not(String propertyTable,HiCriteria hi) {
		DetachedCriteria c =  createSub(propertyTable,this);
		 c.add(Restrictions.not(hi.getCriterion()));
		 return this;
	}
	
	@Override
	public QueryBuilder<T> or(String propertyName,
			SymbolExpression expressions, Object[] objects) {
		SymbolExpression[] se = new SymbolExpression[objects.length]; 
		for(int i=0;i<se.length;i++){
			se[i] = expressions;
		}
		return or(propertyName, se, objects);
	}
	
	@Override
	public QueryBuilder<T> or(String propertyName,	SymbolExpression[] expressions, Object[] objects) {

		String[] proStrings = new String[expressions.length];
		for(int i=0;i<proStrings.length;i++){
			proStrings[i] = propertyName;
		}
		
		return or(proStrings, expressions, objects);
	}
	
	@Override
	public QueryBuilder<T> or(String[] propertyNames,	SymbolExpression[] expressions, Object[] objects) {
		if(propertyNames.length != expressions.length
				&& propertyNames.length !=objects.length){
			throw new MelonException("error propertyNames, expressions or objects ");
		}
		
		if(propertyNames.length==1){
			SymbolExpression.append(this,expressions[0],propertyNames[0],objects[0]);
			return this;
		}
		
		List<OrEntity> list = new ArrayList<OrEntity>();
		for(int i=0;i<propertyNames.length;i++){
			CriEntity cri = seekCriteria(propertyNames[i],this);
			boolean in = false;
			for(OrEntity or : list){
				if(or.equal(cri.getCri())){
					or.add(cri.getPropertyName(),expressions[i], objects[i]);
					in = true;
					break;
				}
			}
			if(!in){
				OrEntity e = new OrEntity();
				e.setCriteria(cri.getCri());
				e.add(cri.getPropertyName(),expressions[i], objects[i]);
				list.add(e);
			}
		}
		
		for(OrEntity or : list){
			HiCriteria criteria = OrCriteria.createMe();
			int i = 1;
			HiCriteria tmpCri = AndCriteria.createMe();
			SymbolExpression.append(tmpCri, or.getExpressions()[0], or.getPropertyNames()[0], or.getValues()[0]);
			
			while(or.getExpressions().length>i){
				HiCriteria hc = AndCriteria.createMe();
				SymbolExpression.append(hc, or.getExpressions()[i], or.getPropertyNames()[i], or.getValues()[i]);
				tmpCri = criteria.add(hc, tmpCri);
				i++;
			}
			or.getCriteria().add(criteria.getCriterion());
		}
		
		return this;
	}
	
	@Override
	public CriteriaSpecification createCriteria(String associationPath) {
		return root.createCriteria(associationPath);
	}
	
	@Override
	public DetachedCriteria getRoot() {
		return root;
	}

	@Override
	public Map<String, DetachedCriteria> getSubCri() {
		return subCri;
	}

	public final static DetachedCriteria createSub(String propertyTable,QueryBuilder qb){
		if(!Validators.isEmpty(propertyTable)){
			String[] tmps = propertyTable.split("\\.");
				String subkey = "";
				String property = "";
				DetachedCriteria parent = qb.getRoot();
				for (int i = 0; i < tmps.length; i++) {
					if (i == 0) {
						subkey = tmps[i];
						property = tmps[i];
					} else {
						subkey = subkey + "." + tmps[i];
						property = tmps[i];
					}
					DetachedCriteria c = (DetachedCriteria) qb.getSubCri().get(subkey);
					if (c == null) {
						DetachedCriteria sub = createSub(parent, property);
						parent = sub;
						qb.getSubCri().put(subkey, parent);
					} else {
						parent = c;
					}
				}
				return (DetachedCriteria) qb.getSubCri().get(subkey);
		}
		return qb.getRoot();
	}

	public final static DetachedCriteria createSub(DetachedCriteria parent, String name) {
		return parent.createCriteria(name);
	}

	/**
	 * 根据key获得criteria节点,若不存在则创建
	 * 
	 * @param key
	 * @return
	 */
	public static final CriEntity seekCriteria(String propertyName,QueryBuilder qb) {
		String[] tmps = propertyName.split("\\.");
		if (tmps.length == 1) {
			return new CriEntity(qb.getRoot(), propertyName);
		}
		String subkey = "";
		String property = "";
		DetachedCriteria parent = qb.getRoot();
		for (int i = 0; i < tmps.length; i++) {
			if (i == 0) {
				subkey = tmps[i];
				property = tmps[i];
			} else {
				subkey = subkey + "." + tmps[i];
				property = tmps[i];
			}
			if (i < tmps.length - 1) {
				DetachedCriteria c = (DetachedCriteria) qb.getSubCri().get(subkey);
				if (c == null) {
					DetachedCriteria sub = createSub(parent, property);
					parent = sub;
					qb.getSubCri().put(subkey, parent);
				} else {
					parent = c;
				}
			}
		}
		return new CriEntity(parent, property);
	}

	public static <E> HibernateQueryBuilder forClass(Class<E> clazz) {
		return new HibernateQueryBuilder(clazz);
	}
	
	public static class CriEntity {
		private DetachedCriteria cri;
		private String propertyName;

		public CriEntity(DetachedCriteria cri, String propertyName) {
			super();
			this.cri = cri;
			this.propertyName = propertyName;
		}

		public DetachedCriteria getCri() {
			return cri;
		}

		public void setCri(DetachedCriteria cri) {
			this.cri = cri;
		}

		public String getPropertyName() {
			return propertyName;
		}

		public void setPropertyName(String propertyName) {
			this.propertyName = propertyName;
		}
	}

	private static class OrEntity{
		private DetachedCriteria criteria;
		private SymbolExpression[] expressions;
		private Object[] values;
		private String[] propertyNames;
		
		public DetachedCriteria getCriteria() {
			return criteria;
		}
		public void setCriteria(DetachedCriteria criteria) {
			this.criteria = criteria;
		}
		public SymbolExpression[] getExpressions() {
			return expressions;
		}
		public Object[] getValues() {
			return values;
		}
		public String[] getPropertyNames() {
			return propertyNames;
		}
		public void add(String propertyName,SymbolExpression expression,Object obj){
			if(expressions==null){
				expressions = new SymbolExpression[1];
				expressions[0] = expression;
				values = new Object[1];
				values[0] = obj;
				propertyNames = new String[1];
				propertyNames[0] = propertyName;
			}else{
				int len = expressions.length;
				SymbolExpression[] tmp = new SymbolExpression[len + 1];
				System.arraycopy(expressions, 0, tmp, 0, len);
				tmp[len] = expression;
				expressions = tmp;
				
				int len2 = values.length;
				Object[] tmp2 = new Object[len2 + 1];
				System.arraycopy(values, 0, tmp2, 0, len2);
				tmp2[len2] = obj;
				values = tmp2;
				
				int len3 = propertyNames.length;
				String[] tmp3 = new String[len3 + 1];
				System.arraycopy(propertyNames, 0, tmp3, 0, len3);
				tmp3[len3] = propertyName;
				propertyNames = tmp3;
			}
		}
		
		public boolean equal(DetachedCriteria cri){
			return criteria == cri;
		}
	}

}



支持使用方法:
entity:
class Foo{
String  id;
String name;
boo b; //在foo中做many-one映射

setter& getter
}

class boo{
String id;
String key;

setter&getter
}

QueryBuilder<Foo> qb = HibernateQueryBuilder.forClass(Foo.class);
qb.eq("name","123"); //查询foo中name是123的数据
qb.in({"id","name","b.id"},{SymbolExpression.EQUAL,SymbolExpression.LIKE,SymbolExpression.LIKE},{"1","2","3"});
//查询 id为1或name为2或left join   b的id为3 的数据

qb.eq("b.name","3");
//SELECT .... FROM   Foo  left join Boo WHERE b.id = f.id AND b.name='3

你可能感兴趣的:(hibernate java)