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