现在的项目对于数据层要求越来越高,常常因为很多原因,不采用一些第三方后台框架,而前台查询业务非常灵活,特别是在分层项目中,体验更为明显。
这个时候我们需要自己来解决一些业务开发中前台和后台的查询透明化,特意自己封装一个查询对象和解析它的方法,主要思想借鉴于hibernate的Criteria 思想,目前版本只支持单表查询。代码下载:源代码
我的自定义查询对象解决几个问题 :
1.前台可以条件随意组合
2.类的序列化和json序列化
3.后台根据未知的前台条件来解析它
看看以下一段测试代码:
public static void main(String[] args) {
Condition con = new Condition(TestPO.class);
//普通条件
Object c = null;
c = RestrictionUtil.eq("tName", "张三");
con.add(c);
c = RestrictionUtil.eq("tName", "男");
con.add(c);
//按 and 的普通条件
Object c1 = null;
Object c2 = null;
c1 = RestrictionUtil.eq("tName2", "张三");
c2 = RestrictionUtil.eq("tName2", "男");
c = RestrictionUtil.and(c1, c2);
con.add(c);
//按or 的普通条件
c1 = RestrictionUtil.eq("tName3", "张三");
c2 = RestrictionUtil.eq("tName3", "男");
c = RestrictionUtil.or(c1, c2);
con.add(c);
//按and 普通条件与 按or的普通条件结合
c1 = RestrictionUtil.eq("tName4", "张三");
c2 = RestrictionUtil.eq("tName4", "男");
c = RestrictionUtil.or(c1, c2);
Object c3 = null;
c3 = RestrictionUtil.eq("tName5", "张三");
c = RestrictionUtil.and(c3, c);
con.add(c);
String json = JsonUtil.toStr(con);
System.out.println(json);
Condition con2 = JsonUtil.toObj(json, Condition.class);
ConditionParse conditionParse = new ConditionParse(con2);
System.out.println(ConditionParseUtil.getSqlWhere(conditionParse));
}
运行结果:
{"simpleObjs":[{"propertyName":"tName","value":"张三","op":"="},{"propertyName":"tName","value":"男","op":"="}],"logicalObjs":[{"lhs":{"propertyName":"tName2","value":"张三","op":"="},"rhs":{"propertyName":"tName2","value":"男","op":"="},"op":"and","lhsType":"SimpleObj","rhsType":"SimpleObj"},{"lhs":{"propertyName":"tName3","value":"张三","op":"="},"rhs":{"propertyName":"tName3","value":"男","op":"="},"op":"or","lhsType":"SimpleObj","rhsType":"SimpleObj"},{"lhs":{"propertyName":"tName5","value":"张三","op":"="},"rhs":{"lhs":{"propertyName":"tName4","value":"张三","op":"="},"rhs":{"propertyName":"tName4","value":"男","op":"="},"op":"or","lhsType":"SimpleObj","rhsType":"SimpleObj"},"op":"and","lhsType":"SimpleObj","rhsType":"LogicalObj"}],"seqList":["SimpleObj","SimpleObj","LogicalObj","LogicalObj","LogicalObj"],"clazz":"com.my.myweb.core.condition.test.TestPO"}
1=1 and tName=? and tName=? and (tName2=? and tName2=?) and (tName3=? or tName3=?) and (tName5=? and (tName4=? or tName4=?))
如上面结果,有将对象进行json序列化,并反序列化回来,用的json也是常用的jackson,并且转成SQL伤代码,其中属性切到字段名,因为不同人做法不一样,我就将属性转字段名切出来了,我本人是用注解的形式是在po上,但其实不少平台都是用xml,但实现这块都是很简单的,就不在里面体现了
以下是我的结构大致介绍:主要看com.my.myweb.core.condition
base:目前存放查询适配器 标准接口
expression:存放表达式适配器
object:存放需要的简单对象和传值对象
parse:解析简单对象的解析类
test:测试需要用到的数据,里面有一个PO对象供测试使用
util:静态工具类
介绍几个重要对象:
条件存放对象:
package com.my.myweb.core.condition;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.my.myweb.core.condition.object.LogicalObj;
import com.my.myweb.core.condition.object.SimpleObj;
/**
* 条件对象
*
* @author zhujie
* @DateTime 2014年8月15日 上午11:46:27
*/
public class Condition implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private List simpleObjs = new ArrayList();
private List logicalObjs = new ArrayList();
private List seqList = new ArrayList();
private Class> clazz;
public Condition() {
}
public Condition(Class> clazz) {
this.clazz = clazz;
}
public void add(Object c) {
if (c == null)
throw new RuntimeException("Criterion is null!");
if (c instanceof SimpleObj) {
seqList.add(SimpleObj.class.getSimpleName());
simpleObjs.add((SimpleObj) c);
} else if (c instanceof LogicalObj) {
seqList.add(LogicalObj.class.getSimpleName());
logicalObjs.add((LogicalObj) c);
}
}
public Class> getClazz() {
return clazz;
}
public void setClazz(Class> clazz) {
this.clazz = clazz;
}
public List getSimpleObjs() {
return simpleObjs;
}
public void setSimpleObjs(List simpleObjs) {
this.simpleObjs = simpleObjs;
}
public List getLogicalObjs() {
return logicalObjs;
}
public void setLogicalObjs(List logicalObjs) {
this.logicalObjs = logicalObjs;
}
public List getSeqList() {
return seqList;
}
public void setSeqList(List seqList) {
this.seqList = seqList;
}
}
对外的添加条件的util 操作
package com.my.myweb.core.condition.util;
import com.my.myweb.core.condition.object.LogicalObj;
import com.my.myweb.core.condition.object.SimpleObj;
/**
* 对外的添加条件的util 操作
* @author zhujie
*
*/
public class RestrictionUtil {
/**
* 等于
* @author zhujie
* @DateTime 2014年8月21日 下午8:56:52
* @param propertyName
* @param value
* @return
*/
public static SimpleObj eq(String propertyName, Object value) {
return new SimpleObj(propertyName, value, "=");
}
/**
* 不等于
* @author zhujie
* @DateTime 2014年8月21日 下午8:57:00
* @param propertyName
* @param value
* @return
*/
public static SimpleObj ne(String propertyName, Object value) {
return new SimpleObj(propertyName, value, "<>");
}
/**
* 模糊
* @author zhujie
* @DateTime 2014年8月21日 下午8:57:08
* @param propertyName
* @param value
* @return
*/
public static SimpleObj like(String propertyName, Object value) {
return new SimpleObj(propertyName, value, " like ");
}
/**
* 大于
* @author zhujie
* @DateTime 2014年8月21日 下午8:57:15
* @param propertyName
* @param value
* @return
*/
public static SimpleObj gt(String propertyName, Object value) {
return new SimpleObj(propertyName, value, ">");
}
/**
* 小于
* @author zhujie
* @DateTime 2014年8月21日 下午8:57:22
* @param propertyName
* @param value
* @return
*/
public static SimpleObj lt(String propertyName, Object value) {
return new SimpleObj(propertyName, value, "<");
}
/**
* 小于等于
* @author zhujie
* @DateTime 2014年8月21日 下午8:57:28
* @param propertyName
* @param value
* @return
*/
public static SimpleObj le(String propertyName, Object value) {
return new SimpleObj(propertyName, value, "<=");
}
/**
* 大于等于
* @author zhujie
* @DateTime 2014年8月21日 下午8:57:33
* @param propertyName
* @param value
* @return
*/
public static SimpleObj ge(String propertyName, Object value) {
return new SimpleObj(propertyName, value, ">=");
}
/**
* 且关系
* @author zhujie
* @DateTime 2014年8月21日 下午8:56:25
* @param lhs
* @param rhs
* @return
*/
public static LogicalObj and(Object lhs, Object rhs) {
return new LogicalObj(lhs, rhs, "and");
}
/**
* 或关系
* @author zhujie
* @DateTime 2014年8月21日 下午8:56:27
* @param lhs
* @param rhs
* @return
*/
public static LogicalObj or(Object lhs, Object rhs) {
return new LogicalObj(lhs, rhs, "or");
}
}
package com.my.myweb.core.condition.parse;
import java.util.ArrayList;
import java.util.List;
import com.my.myweb.core.condition.Condition;
import com.my.myweb.core.condition.base.ExpressionCriterion;
import com.my.myweb.core.condition.expression.LogicalExpression;
import com.my.myweb.core.condition.expression.SimpleExpression;
import com.my.myweb.core.condition.object.LogicalObj;
import com.my.myweb.core.condition.object.SimpleObj;
/**
* 基本BaseParse标准实现的conditionParse
* @author zhujie
*
*/
public class ConditionParse implements BaseParse{
Condition con;
List expressionCriterions = new ArrayList();
private void init(){
int simpleCount = 0;
int logicalCount = 0;
for(String className:con.getSeqList()){
if(className.equals(SimpleObj.class.getSimpleName())){
expressionCriterions.add(new SimpleExpression(con.getSimpleObjs().get(simpleCount++)));
}else if(className.equals(LogicalObj.class.getSimpleName())){
expressionCriterions.add(new LogicalExpression(con.getLogicalObjs().get(logicalCount++)));
}
}
}
public ConditionParse(Condition con){
this.con = con;
init();
}
public Condition getCondition() {
return con;
}
public List getExpressionCriterions() {
return expressionCriterions;
}
public String getFieldNameByPropertyName(String propertyName){
return propertyName;
}
}
package com.my.myweb.core.condition.util;
import java.util.List;
import com.my.myweb.core.condition.Condition;
import com.my.myweb.core.condition.base.ExpressionCriterion;
import com.my.myweb.core.condition.parse.ConditionParse;
import com.my.myweb.core.condition.test.TestPO;
import com.my.myweb.core.util.JsonUtil;
/**
* 对外的获取条件的util 操作
* @author zhujie
*
*/
public class ConditionParseUtil {
public static String getSqlWhere(ConditionParse conditionParse) {
List criterions = conditionParse.getExpressionCriterions();
StringBuffer sqlBuf = new StringBuffer(" 1=1 ");
for (ExpressionCriterion criterion : criterions) {
sqlBuf.append(" and " + criterion.toSqlString(conditionParse));
}
return sqlBuf.toString();
}
public static void main(String[] args) {
Condition con = new Condition(TestPO.class);
//普通条件
Object c = null;
c = RestrictionUtil.eq("tName", "张三");
con.add(c);
c = RestrictionUtil.eq("tName", "男");
con.add(c);
//按 and 的普通条件
Object c1 = null;
Object c2 = null;
c1 = RestrictionUtil.eq("tName2", "张三");
c2 = RestrictionUtil.eq("tName2", "男");
c = RestrictionUtil.and(c1, c2);
con.add(c);
//按or 的普通条件
c1 = RestrictionUtil.eq("tName3", "张三");
c2 = RestrictionUtil.eq("tName3", "男");
c = RestrictionUtil.or(c1, c2);
con.add(c);
//按and 普通条件与 按or的普通条件结合
c1 = RestrictionUtil.eq("tName4", "张三");
c2 = RestrictionUtil.eq("tName4", "男");
c = RestrictionUtil.or(c1, c2);
Object c3 = null;
c3 = RestrictionUtil.eq("tName5", "张三");
c = RestrictionUtil.and(c3, c);
con.add(c);
String json = JsonUtil.toStr(con);
System.out.println(json);
Condition con2 = JsonUtil.toObj(json, Condition.class);
ConditionParse conditionParse = new ConditionParse(con2);
System.out.println(ConditionParseUtil.getSqlWhere(conditionParse));
}
}