精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2006-12-13
我感觉这还是在变相的写SQL呢,而且更麻烦.把SQL的产生封装成了类了一样和OO建模冲突,搞到最后脑子里还是SQL语句然后再转化成你这个类所需要的方法构造出胡来....
|
|
返回顶楼 | |
发表时间:2006-12-13
看看jrc项目:
http://www.iteye.com/topic/21903?page=1 |
|
返回顶楼 | |
发表时间:2006-12-13
blueoxygen 写道 我感觉这还是在变相的写SQL呢,而且更麻烦.把SQL的产生封装成了类了一样和OO建模冲突,搞到最后脑子里还是SQL语句然后再转化成你这个类所需要的方法构造出胡来.... 这个类在限制查询哈是有作用的,我也些过类似的类~
我想这个类要达到的效果是让那些不会sql的人也能查询到想要的东西. |
|
返回顶楼 | |
发表时间:2006-12-13
类似的东西我以前做过,我封装了数据库查询的条件对象和结果集对象,目的是为了实现不同数据库之间的转移。那是一个十分BT的项目,资方希望系统可以在不同数据库平台自由转移,充分利用客户的现有平台,减少拥有成本。
我不能直接用sql做查询条件,因为各种数据库的sql总是有微小的差别。于是我就做了这么一个接口,为各种数据库独立做了一个实现。其实就是为不同的数据库拼接sql。 |
|
返回顶楼 | |
发表时间:2006-12-13
呵呵,我和你的设想一样,我也写了个和你相似的类,不过我这个是用Hibernate作为支持,最后会转化成调用Hibernate的HQL语句。
在我平时的开发中,发现大部分的查询都是查询满足条件的某个MODEL的数据信息,并且条件之间绝大部分是“与”的操作关系,所以我设计了这样的类,并且在我的项目中已经实际运用过,还是满好用的(呵呵,自卖自夸了!)下面给出主要类的代码,具体细节看http://www.iteye.com/topic/37910 我这里设计了这么几个类 1.QueryExpression:存放查询条件,并且我这里允许支持的查询操作比较多 package com.lily.dap.model; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.ToStringBuilder; /** * 查询条件表达式,保存查询条件的一个表达式 * * @author zouxuemo * */ public class QueryExpression { public final static String OP_EQ = "="; //"field = value" public final static String OP_GE = ">="; //"field >= value" public final static String OP_GT = ">"; //"field > value" public final static String OP_LE = "<="; //"field <= value" public final static String OP_LT = "<"; //"field < value" public final static String OP_NE = "<>"; //"field <> value" public final static String OP_LIKE = "like"; //"field like '%value%'" public final static String OP_LLIKE = "llike"; //"field like '%value'" public final static String OP_RLIKE = "rlike"; //"field like 'value%'" public final static String OP_IN = "in"; //"field in (value1, value2, value3, ...)" public final static String OP_NOTIN = "notin"; //"field not in (value1, value2, value3, ...)" public final static String OP_INCLUDE = "include"; //支持查询传入"1-3,5,7-10"这样的查询数据 public final static String OP_INQUERY = "inquery"; //支持IN的子查询(例如:in (select parentId from Item)) public final static String TYPE_STRING = "string"; //参数类型-字符串 public final static String TYPE_NUMBER = "number"; //参数类型-数值 public final static String TYPE_DATE = "date"; //参数类型-日期 public final static String VALUE_SPLIT = ","; /** * 查询条件名称 */ private String name = null; /** * 查询操作 */ private String op = null; /** * 查询值 */ private Object value = null; /** * 查询值类型 */ private String type = null; /** * 构造函数(给定条件名称和条件值,默认查询操作为"=") * * @param name * @param value */ public QueryExpression(String name, Object value) { super(); this.name = name; this.op = OP_EQ; this.value = value; } /** * 构造函数(给定条件名称,操作,条件值) * * @param name * @param op * @param value */ public QueryExpression(String name, String op, Object value) { super(); this.name = name; if (op == null || "".equals(op)) op = OP_EQ; this.op = op; this.value = value; } /** * 构造函数(给定条件名称,操作,条件值,值类型) * * @param name * @param op * @param value * @param type */ public QueryExpression(String name, String op, Object value, String type) { super(); this.name = name; if (op == null || "".equals(op)) op = OP_EQ; this.op = op; this.value = value; this.type = type; } /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the op */ public String getOp() { return op; } /** * @param op the op to set */ public void setOp(String op) { this.op = op; } /** * @return the value */ public Object getValue() { return value; } /** * @param value the value to set */ public void setValue(Object value) { this.value = value; } /** @return Returns the type. */ public String getType() { return type; } /** @param type The type to set. */ public void setType(String type) { this.type = type; } /** * @see java.lang.Object#hashCode() */ public int hashCode() { return new HashCodeBuilder(-159050485, 144990391).appendSuper( super.hashCode()).append(this.op).append(this.value).append( this.type).append(this.name).toHashCode(); } /** * @see java.lang.Object#equals(Object) */ public boolean equals(Object object) { if (!(object instanceof QueryExpression)) { return false; } QueryExpression rhs = (QueryExpression) object; return new EqualsBuilder().appendSuper(super.equals(object)).append( this.op, rhs.op).append(this.value, rhs.value).append( this.type, rhs.type).append(this.name, rhs.name).isEquals(); } /** * @see java.lang.Object#toString() */ public String toString() { return new ToStringBuilder(this).append("name", this.name).append( "value", this.value).append("op", this.op).append("type", this.type).toString(); } } 2.QueryOrder:排序使用的类,存放查询排序字段 package com.lily.dap.model; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; /** * 查询排序类,存放查询排序字段 * * @author zouxuemo * */ public class QueryOrder { public final static String DIR_ASC = "asc"; //按照正序排列 public final static String DIR_DESC = "desc"; //按照倒序排列 /** * 排序字段 */ private String name; /** * 排序方向 */ private String dir; /** * 构造函数(给定排序字段和排序方向) * * @param name * @param dir */ public QueryOrder(String name, String dir) { super(); this.name = name; this.dir = dir; } /** * 构造函数(给定排序名称,默认正序排序) * * @param name */ public QueryOrder(String name) { super(); this.name = name; this.dir = DIR_ASC; } /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the dir */ public String getDir() { return dir; } /** * @param dir the dir to set */ public void setDir(String dir) { this.dir = dir; } /** * @see java.lang.Object#equals(Object) */ public boolean equals(Object object) { if (!(object instanceof QueryOrder)) { return false; } QueryOrder rhs = (QueryOrder) object; return new EqualsBuilder().appendSuper(super.equals(object)).append( this.name, rhs.name).append(this.dir, rhs.dir).isEquals(); } /** * @see java.lang.Object#hashCode() */ public int hashCode() { return new HashCodeBuilder(-745339319, 670215467).appendSuper( super.hashCode()).append(this.name).append(this.dir) .toHashCode(); } /** * @see java.lang.Object#toString() */ public String toString() { return new ToStringBuilder(this).append("name", this.name).append( "dir", this.dir).toString(); } } 3.QueryCondition:存放查询条件集合、排序字段集合、分页信息。如果需要,也可以指定结果字段信息和分组字段信息 package com.lily.dap.model; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; /** * 查询条件实体类,用于传递查询条件内容</p> * 使用方式:</p> * QueryCondition queryCondition = new QueryCondition();</p> * queryCondition.setSelects(new String[]{"class_id", "count(name)"}); //查询给定分类的记录条数 * queryCondition.setGroupbys(new String[]{"class_id"}); //GroupBy分组 * queryCondition.putCondition("id", "-1"); //这个查询条件将忽略</p> * queryCondition.putCondition("username", "admin"); </p> * queryCondition.putCondition("name", QueryExpression.OP_IN, "张三,李四,王五");</p> * queryCondition.putCondition("birthday", QueryExpression.OP_GE, "2005-12-31");</p> * queryCondition.putCondition("birthday", QueryExpression.OP_LE, "2006-12-31");</p> * queryCondition.addOrder("username"); //设置查询进行排序</p> * queryCondition.setPageSize(10); //设置查询结果实现翻页,每页10条记录</p> * queryCondition.setPageNo(2); //设置查询结果实现翻页,显示第二页记录</p> * List list = dao.gets(Register.class, queryCondition);</p> * 将生成查询条件如下:</p> * from com.lily.dap.model.Register where username = 'admin' and name in ('张三', '李四', '王五') and</p> * birthday >= '2005-12-31' and birthday <= '2006-12-31' order by username asc</p> * * queryCondition.putCondition("cond0", null); * assertEquals("", queryCondition.getCondition("cond0").getValue()); * * queryCondition.putCondition("cond1", "value1"); * assertEquals("value1", queryCondition.getCondition("cond1").getValue()); * * SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); * queryCondition.putCondition("cond2", sdf.parse("2006-12-31")); * assertEquals("2006-12-31 00:00:00", queryCondition.getCondition("cond2").getValue()); * * queryCondition.putCondition("cond3", new long[]{1,2,3}); * assertEquals("1,2,3", queryCondition.getCondition("cond3").getValue()); * * queryCondition.putCondition("cond4", new int[]{100,200,300}); * assertEquals("100,200,300", queryCondition.getCondition("cond4").getValue()); * * queryCondition.putCondition("cond5", new String[]{"aa", "bb", "cc"}); * assertEquals("aa,bb,cc", queryCondition.getCondition("cond5").getValue()); * * List list = new ArrayList(); * list.add("aaa"); * list.add(new Long(1234)); * queryCondition.putCondition("cond6", list); * assertEquals("aaa,1234", queryCondition.getCondition("cond6").getValue()); * * queryCondition.putCondition("cond7", new Long(123)); * assertEquals("123", queryCondition.getCondition("cond7").getValue()); * * queryCondition.putCondition("cond8", new Boolean(true)); * assertEquals("true", queryCondition.getCondition("cond8").getValue()); * * queryCondition.putCondition("cond9", new Float(33.3333f)); * assertEquals("33.3333", queryCondition.getCondition("cond9").getValue()); * * @author zouxuemo */ public class QueryCondition extends BaseObject { /** Comment for <code>serialVersionUID</code> */ private static final long serialVersionUID = -5970921549911182011L; /** 选择列数组 */ protected String[] selects = null; /** Group By 数组 */ protected String[] groupbys = null; /** * 查询条件列表,存放QueryExpression对象 * * <code>conditions</code> */ protected List conditions = new ArrayList(); /** * 排序字段列表,存放QueryOrder对象 * * <code>orders</code> */ protected List orders = new ArrayList(); /** * 从查询结果返回的页号,默认为0表示不分页 * * <code>pageNo</code> */ protected int pageNo = 0; /** * 从查询结果返回的每页记录条数,默认0:表示不分页 * * <code>pageSize</code> */ protected int pageSize = 0; private Iterator itCondition = null; private Iterator itOrder = null; /** @return Returns the selects. */ public String[] getSelects() { return selects; } /** @param selects The selects to set. */ public QueryCondition setSelects(String[] selects) { this.selects = selects; return this; } /** @return Returns the groupbys. */ public String[] getGroupbys() { return groupbys; } /** @param groupbys The groupbys to set. */ public QueryCondition setGroupbys(String[] groupbys) { this.groupbys = groupbys; return this; } /** * @return the conditions */ public List getConditions() { return conditions; } /** * @param conditions the conditions to set */ public void setConditions(List conditions) { this.conditions = conditions; } /** * 添加等于操作的条件表达式,指定条件名称、条件值,默认查询操作为"=",并且不覆盖有同样名的查询条件 * * @param condition_name * @param condition_value * @return */ public QueryCondition putCondition(String condition_name, Object condition_value) { return putCondition(condition_name, QueryExpression.OP_EQ, condition_value, false); } /** * 添加等于操作的条件表达式,指定条件名称、条件值,指定是否覆盖有同样名的查询条件,指定覆盖,则如果条件名称已经存在,覆盖原有条件 * * @param condition_name * @param condition_value * @param isReplaceRepeat * @return */ public QueryCondition putCondition(String condition_name, Object condition_value, boolean isReplaceRepeat) { return putCondition(condition_name, QueryExpression.OP_EQ, condition_value, isReplaceRepeat); } /** * 添加条件表达式,指定条件名称、条件操作、条件值,默认不覆盖有同样名的查询条件 * * @param condition_name * @param condition_op * @param condition_value * @return */ public QueryCondition putCondition(String condition_name, String condition_op, Object condition_value) { return putCondition(condition_name, condition_op, condition_value, false); } /** * 添加条件表达式,指定条件名称、条件操作、条件值,指定是否覆盖有同样名的查询条件,指定覆盖,则如果条件名称已经存在,覆盖原有条件 * * @param condition_name * @param condition_op * @param condition_value * @param isReplaceRepeat * @return */ public QueryCondition putCondition(String condition_name, String condition_op, Object condition_value, boolean isReplaceRepeat) { if (isReplaceRepeat) removeCondition(condition_name); if (condition_value == null) condition_value = ""; conditions.add(new QueryExpression(condition_name, condition_op, condition_value)); return this; } /** * 添加条件表达式,指定条件名称、条件操作、条件值、条件值类型,指定是否覆盖有同样名的查询条件,指定覆盖,则如果条件名称已经存在,覆盖原有条件 * * @param condition_name * @param condition_op * @param condition_value * @param conditin_type * @param isReplaceRepeat * @return */ public QueryCondition putCondition(String condition_name, String condition_op, Object condition_value, String conditin_type, boolean isReplaceRepeat) { if (isReplaceRepeat) removeCondition(condition_name); if (condition_value == null) condition_value = ""; conditions.add(new QueryExpression(condition_name, condition_op, condition_value, conditin_type)); return this; } /** * 添加等于操作的条件表达式,指定条件名称、条件值,默认查询操作为"=",并且不覆盖有同样名的查询条件 * * @param condition_name * @param condition_value * @return */ public QueryCondition putCondition(String condition_name, long condition_value) { return putCondition(condition_name, QueryExpression.OP_EQ, condition_value, false); } /** * 添加等于操作的条件表达式,指定条件名称、条件值,指定是否覆盖有同样名的查询条件,指定覆盖,则如果条件名称已经存在,覆盖原有条件 * * @param condition_name * @param condition_value * @param isReplaceRepeat * @return */ public QueryCondition putCondition(String condition_name, long condition_value, boolean isReplaceRepeat) { return putCondition(condition_name, QueryExpression.OP_EQ, condition_value, isReplaceRepeat); } /** * 添加条件表达式,指定条件名称、条件操作、条件值,默认不覆盖有同样名的查询条件 * * @param condition_name * @param condition_op * @param condition_value * @return */ public QueryCondition putCondition(String condition_name, String condition_op, long condition_value) { return putCondition(condition_name, condition_op, condition_value, false); } /** * 添加条件表达式,指定条件名称、条件操作、条件值,指定是否覆盖有同样名的查询条件,指定覆盖,则如果条件名称已经存在,覆盖原有条件 * * @param condition_name * @param condition_op * @param condition_value * @param isReplaceRepeat * @return */ public QueryCondition putCondition(String condition_name, String condition_op, long condition_value, boolean isReplaceRepeat) { if (isReplaceRepeat) removeCondition(condition_name); conditions.add(new QueryExpression(condition_name, condition_op, new Long(condition_value))); return this; } /** * 添加等于操作的条件表达式,指定条件名称、条件值,默认查询操作为"=",并且不覆盖有同样名的查询条件 * * @param condition_name * @param condition_value * @return */ public QueryCondition putCondition(String condition_name, int condition_value) { return putCondition(condition_name, QueryExpression.OP_EQ, condition_value, false); } /** * 添加等于操作的条件表达式,指定条件名称、条件值,指定是否覆盖有同样名的查询条件,指定覆盖,则如果条件名称已经存在,覆盖原有条件 * * @param condition_name * @param condition_value * @param isReplaceRepeat * @return */ public QueryCondition putCondition(String condition_name, int condition_value, boolean isReplaceRepeat) { return putCondition(condition_name, QueryExpression.OP_EQ, condition_value, isReplaceRepeat); } /** * 添加条件表达式,指定条件名称、条件操作、条件值,默认不覆盖有同样名的查询条件 * * @param condition_name * @param condition_op * @param condition_value * @return */ public QueryCondition putCondition(String condition_name, String condition_op, int condition_value) { return putCondition(condition_name, condition_op, condition_value, false); } /** * 添加条件表达式,指定条件名称、条件操作、条件值,指定是否覆盖有同样名的查询条件,指定覆盖,则如果条件名称已经存在,覆盖原有条件 * * @param condition_name * @param condition_op * @param condition_value * @param isReplaceRepeat * @return */ public QueryCondition putCondition(String condition_name, String condition_op, int condition_value, boolean isReplaceRepeat) { if (isReplaceRepeat) removeCondition(condition_name); conditions.add(new QueryExpression(condition_name, condition_op, new Integer(condition_value))); return this; } /* ******************** * * 暂时屏蔽 * 把浮点数作为查询对象的情况很少见,这里就不对这个特例专门编写方法了 * 如果非要用,可以调用上面提供的方法同样可以实现这种查询 * * ********************/ // /** // * 添加等于操作的条件表达式,指定条件名称、条件值,默认查询操作为"=",并且不覆盖有同样名的查询条件 // * // * @param condition_name // * @param condition_value // * @return // */ // public QueryCondition putCondition(String condition_name, double condition_value) { // return putCondition(condition_name, QueryExpression.OP_EQ, condition_value, false); // } // // /** // * 添加等于操作的条件表达式,指定条件名称、条件值,指定是否覆盖有同样名的查询条件,指定覆盖,则如果条件名称已经存在,覆盖原有条件 // * // * @param condition_name // * @param condition_value // * @param isReplaceRepeat // * @return // */ // public QueryCondition putCondition(String condition_name, double condition_value, boolean isReplaceRepeat) { // return putCondition(condition_name, QueryExpression.OP_EQ, condition_value, isReplaceRepeat); // } // // /** // * 添加条件表达式,指定条件名称、条件操作、条件值,默认不覆盖有同样名的查询条件 // * // * @param condition_name // * @param condition_op // * @param condition_value // * @return // */ // public QueryCondition putCondition(String condition_name, String condition_op, double condition_value) { // return putCondition(condition_name, condition_op, condition_value, false); // } // // /** // * 添加条件表达式,指定条件名称、条件操作、条件值,指定是否覆盖有同样名的查询条件,指定覆盖,则如果条件名称已经存在,覆盖原有条件 // * // * @param condition_name // * @param condition_op // * @param condition_value // * @param isReplaceRepeat // * @return // */ // public QueryCondition putCondition(String condition_name, String condition_op, double condition_value, boolean isReplaceRepeat) { // if (isReplaceRepeat) // removeCondition(condition_name); // // conditions.add(new QueryExpression(condition_name, condition_op, new Double(condition_value))); // return this; // } /* ******************** * * 暂时屏蔽 * 下面的传入布尔型的方法会和 * putCondition(String condition_name, Object condition_value, boolean isReplaceRepeat)冲突 * 为了防止出现使用错误,先屏蔽该方法 * * ********************/ // /** // * 添加等于操作的条件表达式,指定条件名称、条件值,默认查询操作为"=",并且不覆盖有同样名的查询条件 // * // * @param condition_name // * @param condition_value // * @return // */ // public QueryCondition putCondition(String condition_name, boolean condition_value) { // return putCondition(condition_name, QueryExpression.OP_EQ, condition_value, false); // } // // /** // * 添加等于操作的条件表达式,指定条件名称、条件值,指定是否覆盖有同样名的查询条件,指定覆盖,则如果条件名称已经存在,覆盖原有条件 // * // * @param condition_name // * @param condition_value // * @param isReplaceRepeat // * @return // */ // public QueryCondition putCondition(String condition_name, boolean condition_value, boolean isReplaceRepeat) { // return putCondition(condition_name, QueryExpression.OP_EQ, condition_value, isReplaceRepeat); // } // // /** // * 添加条件表达式,指定条件名称、条件操作、条件值,默认不覆盖有同样名的查询条件 // * // * @param condition_name // * @param condition_op // * @param condition_value // * @return // */ // public QueryCondition putCondition(String condition_name, String condition_op, boolean condition_value) { // return putCondition(condition_name, condition_op, condition_value, false); // } // // /** // * 添加条件表达式,指定条件名称、条件操作、条件值,指定是否覆盖有同样名的查询条件,指定覆盖,则如果条件名称已经存在,覆盖原有条件 // * // * @param condition_name // * @param condition_op // * @param condition_value // * @param isReplaceRepeat // * @return // */ // public QueryCondition putCondition(String condition_name, String condition_op, boolean condition_value, boolean isReplaceRepeat) { // if (isReplaceRepeat) // removeCondition(condition_name); // // conditions.add(new QueryExpression(condition_name, condition_op, new Boolean(condition_value))); // return this; // } /** * 去除给定名称的条件表达式,如果有多个同名的条件表达式,则删除第一个找到的条件表达式 * * @param condition_name */ public void removeCondition(String condition_name) { QueryExpression queryExpression = getCondition(condition_name); if (queryExpression != null) conditions.remove(queryExpression); } /** * 清除所有的查询条件 */ public void clearCondition() { while (conditions.size() > 0) conditions.remove(0); } /** * 检索给定表达式名称找到的第一个表达式,如果没有找到满足条件的表达式,返回null * * @param condition_name * @return */ public QueryExpression getCondition(String condition_name) { Iterator it = conditions.iterator(); while (it.hasNext()) { QueryExpression queryExpression = (QueryExpression)it.next(); if (condition_name.equals(queryExpression.getName())) return queryExpression; } return null; } /** * 开始进行查询条件遍历 * */ public void beginFindCondition() { itCondition = conditions.iterator(); } /** * 遍历搜索下一个查询条件,如果已经遍历完成,返回null * * @return */ public QueryExpression findNextCondition() { if (itCondition == null) beginFindCondition(); if (itCondition.hasNext()) return (QueryExpression)itCondition.next(); else return null; } /** * @return the orders */ public List getOrders() { return orders; } /** * @param orders the orders to set */ public void setOrders(List orders) { this.orders = orders; } /** * 添加排序字段,指定排序字段和排序顺序,如果有同名的排序字段,则覆盖排序方向 * * @param order_name * @param order_dir * @return */ public QueryCondition addOrder(String order_name, String order_dir) { QueryOrder queryOrder = getOrder(order_name); if (!QueryOrder.DIR_ASC.equals(order_dir) && !QueryOrder.DIR_DESC.equals(order_dir)) order_dir = QueryOrder.DIR_ASC; if (queryOrder != null) queryOrder.setDir(order_dir); else orders.add(new QueryOrder(order_name, order_dir)); return this; } /** * 添加排序字段,默认为正序排序 * * @param order_name * @return */ public QueryCondition addOrder(String order_name) { return addOrder(order_name, QueryOrder.DIR_ASC); } /** * 删除指定名称的排序字段 * * @param order_name */ public void removeOrder(String order_name) { QueryOrder queryOrder = getOrder(order_name); if (queryOrder != null) orders.remove(queryOrder); } /** * 清除所有的排序字段 */ public void clearOrder() { while (orders.size() > 0) orders.remove(0); } /** * 返回指定名称的排序信息 * * @param order_name * @return */ public QueryOrder getOrder(String order_name) { Iterator it = orders.iterator(); while (it.hasNext()) { QueryOrder queryOrder = (QueryOrder)it.next(); if (order_name.equals(queryOrder.getName())) return queryOrder; } return null; } /** * 开始遍历排序条件 */ public void beginFindOrder() { itOrder = orders.iterator(); } /** * 遍历下一个排序条件,如果已经遍历完成,则返回null * @return */ public QueryOrder findNextOrder() { if (itOrder == null) beginFindOrder(); if (itOrder.hasNext()) return (QueryOrder)itOrder.next(); else return null; } /** * 返回当前查询的分页页号 * * @return the pageNo */ public int getPageNo() { return pageNo; } /** * 设置当前查询的分页页号 * * @param pageNo the pageNo to set */ public QueryCondition setPageNo(int pageNo) { this.pageNo = pageNo; return this; } /** * 返回当前查询的分页每页记录数 * * @return the pageSize */ public int getPageSize() { return pageSize; } /** * 设置当前查询的分页每页记录数 * * @param pageSize the pageSize to set */ public QueryCondition setPageSize(int pageSize) { this.pageSize = pageSize; return this; } /** * @see java.lang.Object#equals(Object) */ public boolean equals(Object object) { if (!(object instanceof QueryCondition)) { return false; } QueryCondition rhs = (QueryCondition) object; return new EqualsBuilder().append( this.selects, rhs.selects).append(this.groupbys, rhs.groupbys) .append(this.orders, rhs.orders).append(this.pageSize, rhs.pageSize) .append(this.conditions, rhs.conditions).append(this.pageNo, rhs.pageNo) .isEquals(); } /** * @see java.lang.Object#hashCode() */ public int hashCode() { return new HashCodeBuilder(-2021626145, -489366831) .append(this.selects) .append(this.conditions) .append(this.groupbys) .append(this.orders) .append(this.pageSize) .append(this.pageNo) .toHashCode(); } /** * @see java.lang.Object#toString() */ public String toString() { return new ToStringBuilder(this) .append("selects", this.selects) .append("conditions", this.conditions) .append("groupbys", this.groupbys) .append("orders", this.orders) .append("pageSize", this.pageSize) .append("pageNo", this.pageNo) .toString(); } } 4.AbstractDaoHibernate:查询实现,把QueryCondition中的查询条件集合最后构造成HQL语法,交给Hibernate去执行,返回查询对象List集合 package com.lily.dap.dao.hibernate; import java.io.Serializable; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.type.Type; import org.springframework.orm.ObjectRetrievalFailureException; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import com.lily.dap.Constants; import com.lily.dap.dao.Dao; import com.lily.dap.dao.QueryCallback; import com.lily.dap.dao.TransitionCallback; import com.lily.dap.dao.support.DaoHelper; import com.lily.dap.model.QueryCondition; import com.lily.dap.model.QueryExpression; import com.lily.dap.model.QueryOrder; /** * @author zouxuemo * */ public class AbstractDaoHibernate extends HibernateDaoSupport implements Dao { protected final Log logger = LogFactory.getLog(getClass()); /* (non-Javadoc) * @see com.lily.dap.dao.BasetDao#get(java.lang.Class, java.io.Serializable) */ public Object get(Class clazz, Serializable id) throws ObjectRetrievalFailureException { Object o = getHibernateTemplate().get(clazz, id); if (o == null) { logger.warn("给定id为[" + id + "]的" + clazz.getName() + "对象没找到..."); throw new ObjectRetrievalFailureException(clazz, id); } return o; } /* (non-Javadoc) * @see com.lily.dap.dao.BasetDao#save(java.lang.Object) */ public void save(Object o) { getHibernateTemplate().saveOrUpdate(o); } /* (non-Javadoc) * @see com.lily.dap.dao.BasetDao#remove(java.lang.Class, java.io.Serializable) */ public void remove(Class clazz, Serializable id) throws ObjectRetrievalFailureException { remove(get(clazz, id)); } public void remove(Object entity) { getHibernateTemplate().delete(entity); } /* (non-Javadoc) * @see com.lily.dap.dao.BasetDao#reload(java.lang.Object) */ public void reload(Object object) { getHibernateTemplate().refresh(object); } /* (non-Javadoc) * @see com.lily.dap.dao.BasetDao#gets(java.lang.Class, com.lily.dap.model.QueryCondition) */ public List gets(Class clazz, QueryCondition queryCondition) { return gets(clazz, queryCondition, null); } /* (non-Javadoc) * @see com.lily.dap.dao.BasetDao#gets(java.lang.Class, com.lily.dap.model.QueryCondition, com.lily.dap.model.QueryCallBack) */ public List gets(Class clazz, QueryCondition queryCondition, QueryCallback callBack) { String hql = parseQueryCondition(clazz, queryCondition, callBack); if ( logger.isDebugEnabled() ) { logger.debug("gets - [" + hql + "]..."); } return executeFind(hql, queryCondition.getPageNo(), queryCondition.getPageSize()); } public long count(Class clazz, QueryCondition queryCondition) { return count(clazz, queryCondition, null); } public long count(Class clazz, QueryCondition queryCondition, QueryCallback callBack) { String hql = parseQueryCondition(clazz, queryCondition, callBack); int index = hql.indexOf("group by"); if (index < 0) index = hql.indexOf("order by"); if (index >= 0) hql = hql.substring(0, index); hql = "select count(*) " + hql.substring(hql.indexOf("from")); if ( logger.isDebugEnabled() ) { logger.debug("count - [" + hql + "]..."); } List result = executeFind(hql); long count = 0; if (result.size() > 0) count = ((Long)result.get(0)).longValue(); return count; } private String parseQueryCondition(Class clazz, QueryCondition queryCondition, QueryCallback callBack) { StringBuffer buf = new StringBuffer(); //如果指定了要返回的字段,则构造选择字段的HQL语句 if (queryCondition.getSelects() != null && queryCondition.getSelects().length > 0) { String[] selects = queryCondition.getSelects(); buf.append("select ").append(selects[0]); for (int i = 1; i < selects.length; i++) buf.append(",").append(selects[i]); buf.append(" "); } buf.append("from ").append(clazz.getName()).append(" where "); //从查询表达式列表读取查询表达式,检查表达式字段是否属于类中的属性值,检查表达式操作是否支持,构造HQL条件语句 queryCondition.beginFindCondition(); QueryExpression expression; while ((expression = queryCondition.findNextCondition()) != null) { if (callBack != null) { String cond = callBack.parseCondition(expression); if (cond != null && !"".equals(cond)){ if (!QueryCallback.IGRONE.equals(cond)) buf.append(cond).append(" and "); continue; } } String name = expression.getName(); Class type; Method method = null; try { method = DaoHelper.getMethod(clazz, name); } catch (SecurityException e) { logger.warn("给定的查询字段[" + name + "]在[" + clazz.getName() + "]类中不允许操作!"); continue; } catch (NoSuchMethodException e) { logger.warn("给定的查询字段[" + name + "]在[" + clazz.getName() + "]类中不存在!"); continue; } type = method.getReturnType(); String expressionType = expression.getType(); boolean isSingleQuotesFlag = false; if (expressionType != null) { if(QueryExpression.TYPE_STRING.equals(expressionType) || QueryExpression.TYPE_DATE.equals(expressionType)) isSingleQuotesFlag = true; } else if (type == String.class || type == Date.class || type == Time.class || type == Timestamp.class) { isSingleQuotesFlag = true; } String value = DaoHelper.expressionValue2String(expression.getValue()); //如果是数值型,则如果条件值为Constants.RETRIEVE_ALL时忽略该条件。如果是字符串型,则如果条件值为空字符串时忽略该条件 if ("long".equals(type.getName()) || "int".equals(type.getName()) || type == Long.class || type == Integer.class) { if (value.equals(String.valueOf(Constants.RETRIEVE_ALL))) continue; } else if (type == String.class) { if ("".equals(value)) continue; } //其他类型就要求提供查询值 if ("".equals(value)) { logger.warn("给定的查询字段[" + name + ":" + type.getName() + "]必须输入查询条件值!"); continue; } String op = expression.getOp(); if (QueryExpression.OP_EQ.equals(op) || QueryExpression.OP_NE.equals(op) || QueryExpression.OP_GE.equals(op) || QueryExpression.OP_GT.equals(op) || QueryExpression.OP_LE.equals(op) || QueryExpression.OP_LT.equals(op)) { buf.append(name).append(" ").append(op).append(" "); if (isSingleQuotesFlag) buf.append("'").append(value).append("'"); else buf.append(value); buf.append(" and "); } else if (QueryExpression.OP_LIKE.equals(op)) { buf.append(name).append(" like '%").append(value).append("%' and "); } else if (QueryExpression.OP_LLIKE.equals(op)) { buf.append(name).append(" like '%").append(value).append("' and "); } else if (QueryExpression.OP_RLIKE.equals(op)) { buf.append(name).append(" like '").append(value).append("%' and "); } else if (QueryExpression.OP_IN.equals(op) || QueryExpression.OP_NOTIN.equals(op)) { if (QueryExpression.OP_IN.equals(op)) buf.append(name).append(" in ("); else buf.append(name).append(" not in ("); StringTokenizer valuest = new StringTokenizer(value, QueryExpression.VALUE_SPLIT); int c = 0; while (valuest.hasMoreTokens()) { String val = valuest.nextToken(); if (c++ > 0) buf.append(", "); if (isSingleQuotesFlag) buf.append("'").append(val).append("'"); else buf.append(val); } buf.append(") and "); } else if (QueryExpression.OP_INCLUDE.equals(op)) { int[] ary = DaoHelper.parseNumExpression(value); if (ary.length == 0) { logger.warn("给定的include查询操作值[" + value + "]格式错误!"); continue; } buf.append(name).append(" in (").append(ary[0]); for (int i = 1; i < ary.length; i++) buf.append(", ").append(ary[0]); buf.append(") and "); } else if (QueryExpression.OP_INQUERY.equals(op)) { buf.append(name).append(" in (").append(value).append(") and "); } else { logger.warn("对" + name + "的查询操作[" + op + "]不可识别!"); continue; } } if (" and ".equals(buf.substring(buf.length() - 5))) buf = buf.delete(buf.length() - 5, buf.length()); else buf = buf.delete(buf.length() - 7, buf.length()); if (queryCondition.getGroupbys() != null && queryCondition.getGroupbys().length > 0) { String[] groupbys = queryCondition.getGroupbys(); buf.append(" group by ").append(groupbys[0]); for (int i = 1; i < groupbys.length; i++) buf.append(",").append(groupbys[i]); buf.append(" "); } //从排序列表读取排序字段,检查排序字段是否属于类中的属性值,检查排序方式是否支持,构造HQL排序语句 buf.append(" order by "); queryCondition.beginFindOrder(); QueryOrder order; while ((order = queryCondition.findNextOrder()) != null) { String name = order.getName(); String dir = order.getDir(); // try { // Method method = DaoHelper.getMethod(name, clazz); // } catch (SecurityException e) { // logger.warn("给定的排序字段[" + name + "]在[" + clazz.getName() + "]类中不允许操作!"); // continue; // } catch (NoSuchMethodException e) { // logger.warn("给定的排序字段[" + name + "]在[" + clazz.getName() + "]类中不存在!"); // continue; // } buf.append(name).append(" ").append(dir).append(", "); } if (", ".equals(buf.substring(buf.length() - 2))) buf = buf.delete(buf.length() - 2, buf.length()); else buf = buf.delete(buf.length() - 10, buf.length()); return buf.toString(); } public List executeFind(final String hql) { return executeFind(hql, null, null, 0, 0); } public List executeFind(final String hql, final Object[] args, final Type[] types) { return executeFind(hql, args, types, 0, 0); } public List executeFind(final String hql, final int pageNo, final int pageSize) { return executeFind(hql, null, null, pageNo, pageSize); } public List executeFind(final String hql, final Object[] args, final Type[] types, final int pageNo, final int pageSize) { return getHibernateTemplate().executeFind(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Query query = session.createQuery(hql); if ( args != null ) { for ( int i = 0; i < args.length; i++ ) { Object arg = args[i]; Type type = null; if ( types != null && i < types.length ) { type = types[i]; } if ( type == null ) { query.setParameter(i, arg); } else { query.setParameter(i, arg, type); } } } if (pageSize > 0) { int offset = (pageNo - 1) * pageSize; int limit = pageSize; query.setFirstResult(offset); query.setMaxResults(limit); if ( logger.isDebugEnabled() ) { logger.debug("查询结果实现翻页,每页" + pageSize + "条记录,翻页到第" + pageNo + "页..."); } } List list = query.list(); if (list == null) list = new ArrayList(); return list; } }); } public Object findUniqueResult(final String hql) { return findUniqueResult(hql, null, null); } public Object findUniqueResult(final String hql, final Object[] args, final Type[] types) { return getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Query query = session.createQuery(hql); if ( args != null ) { for ( int i = 0; i < args.length; i++ ) { Object arg = args[i]; Type type = null; if ( types != null && i < types.length ) { type = types[i]; } if ( type == null ) { query.setParameter(i, arg); } else { query.setParameter(i, arg, type); } } } query.setMaxResults(1); return query.uniqueResult(); } }); } public void executeSQLUpdate(final String sql) throws Exception { executeSQLUpdate(sql, null, null); } public void executeSQLUpdate(final String sql, final Object[] args, final String[] types) throws Exception { Session session = getSession(); Connection connection = session.connection(); PreparedStatement pstmt = null; try { pstmt = connection.prepareStatement(sql); if ( args != null ) { for ( int i = 0; i < args.length; i++ ) { Object arg = args[i]; String type = null; if ( types != null && i < types.length ) { type = types[i]; } int index = i + 1; if ("String".equals(type)) { pstmt.setString(index, (String)arg); } else if ("long".equals(type) || "Long".equals(type)) { pstmt.setLong(index, ((Long)arg).longValue()); } else if ("int".equals(type) || "Integer".equals(type)) { pstmt.setInt(index, ((Integer)arg).intValue()); } else if ("double".equals(type) || "Double".equals(type)) { pstmt.setDouble(index, ((Double)arg).doubleValue()); } else if ("float".equals(type) || "Float".equals(type)) { pstmt.setFloat(index, ((Float)arg).floatValue()); } else if ("Date".equals(type)) { java.sql.Date date = null; if (arg instanceof java.util.Date) { date = new java.sql.Date(((java.util.Date)arg).getTime()); } else if (arg instanceof java.sql.Date) date = (java.sql.Date)arg; else date = new java.sql.Date(new SimpleDateFormat("yyyy-MM-dd").parse((String)arg).getTime()); pstmt.setDate(index, date); } else if ("Time".equals(type)) { pstmt.setTime(index, (Time)arg); } else if ("Timestamp".equals(type)) { pstmt.setTimestamp(index, (Timestamp)arg); } } } pstmt.executeUpdate(); } catch(Exception e) { throw e; } finally { try { if (pstmt != null) pstmt.close(); } catch (Exception e) { } } } public ResultSet executeSQLQuery(String sql) { return executeSQLQuery(sql, 0, 0); } public ResultSet executeSQLQuery(String sql, final int pageNo, final int pageSize) { logger.debug("executeSQLQuery - [" + sql + "]..."); if (pageSize > 0) logger.debug("每页" + pageSize + "条,翻页到第" + pageNo + "页"); Connection conn = this.getSession().connection(); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); if (pageSize > 0) { int offset = (pageNo - 1) * pageSize; int maxRows = offset + pageSize; pstmt.setMaxRows(maxRows); rs = pstmt.executeQuery(); rs.absolute(offset); } else rs = pstmt.executeQuery(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("Execute retrieve sql " + sql + " failed"); } return rs; } public long executeSQLCount(String sql) { int index = sql.indexOf("order by"); if (index >= 0) sql = sql.substring(0, index); sql = "select count(0) from (" + sql + ") mytable"; if ( logger.isDebugEnabled() ) { logger.debug("executeSQLCount - [" + sql + "]..."); } Connection conn = this.getSession().connection(); PreparedStatement pstmt = null; ResultSet rs = null; long count = 0; try { pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); if(rs.next()) count = rs.getLong(1); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("Execute retrieve sql " + sql + " failed"); } return count; } public List ResultSet2List(ResultSet rs, TransitionCallback callback) { List list = new ArrayList(); try { while (rs.next()) { Object obj = callback.transition(rs); list.add(obj); } } catch (SQLException e) { throw new RuntimeException( "SQLException Exception encountered", e); } return list; } public List ResultSet2List(ResultSet rs) { int columnCount = 0; String[] columnNames = null; try { ResultSetMetaData resultSetMetaData = rs.getMetaData(); columnCount = resultSetMetaData.getColumnCount(); columnNames = new String[columnCount+1]; for (int i = 1; i <= columnCount; i++) { columnNames[i] = resultSetMetaData.getColumnName(i); } } catch (SQLException e) { throw new RuntimeException( "SQLException Exception encountered", e); } List list = new ArrayList(); try { while (rs.next()) { Map map = new HashMap(); for (int i = 1; i <= columnCount; i++) map.put(columnNames[i], rs.getObject(i)); list.add(map); } } catch (SQLException e2) { throw new RuntimeException( "SQLException Exception encountered", e2); } return list; } } 5.DaoHelper:查询辅助类 package com.lily.dap.dao.support; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.Iterator; import org.apache.commons.lang.StringUtils; import com.lily.dap.model.QueryExpression; /** * @author zouxuemo * */ public class DaoHelper { private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static String expressionValue2String(Object value) { String v = null; if (value == null) v = ""; else if (value instanceof String) v = (String)value; else if (value instanceof Date) v = sdf.format((Date)value); else if (value instanceof long[]) { long[] ary = (long[])value; if (ary.length > 0) { StringBuffer sb = new StringBuffer().append(ary[0]); for (int i = 1; i < ary.length; i++) sb.append(QueryExpression.VALUE_SPLIT).append(ary[i]); v = sb.toString(); } } else if (value instanceof int[]) { int[] ary = (int[])value; if (ary.length > 0) { StringBuffer sb = new StringBuffer().append(ary[0]); for (int i = 1; i < ary.length; i++) sb.append(QueryExpression.VALUE_SPLIT).append(ary[i]); v = sb.toString(); } } else if (value instanceof Object[]) { v = StringUtils.join((Object[])value, QueryExpression.VALUE_SPLIT); } else if (value instanceof Collection) { Iterator it = ((Collection)value).iterator(); v = StringUtils.join(it, QueryExpression.VALUE_SPLIT); } else //Long Integer Double Float Boolean v = value.toString(); return v; } /** * 分析数字表达式,并返回其中定义的数字数组<p> * 数字表达式格式为:"1-4","1,3,5,7","1-3,5,7-10",其中,1-4表示:1至4,1,3,5,7表示:1 3 5 7 * * @param expression 要分析的表达式 * @return 返回按照大小排序的整数数组 */ public static int[] parseNumExpression(String expression) { if (expression == null || "".equals(expression)) return new int[0]; int[] temp = new int[1000]; int ptr = 0; String[] tokens = expression.split(","); for (int i = 0; i < tokens.length; i++) { try { int i_val = Integer.parseInt(tokens[i].trim()); temp[ptr++] = i_val; } catch (NumberFormatException e) { String[] tmp = tokens[i].split("-"); if (tmp.length == 2) { int bg = 0, ed = 0; try { bg = Integer.parseInt(tmp[0].trim()); ed = Integer.parseInt(tmp[1].trim()); } catch (NumberFormatException e1) { continue; } for (int ii = bg; ii <= ed; ii++) { temp[ptr++] = ii; } } } } if (ptr == 0) return new int[0]; Arrays.sort(temp, 0, ptr); int length = 1, old = temp[0]; for (int i = 1; i < ptr; i++) { if (old != temp[i]) { length++; old = temp[i]; } } int[] ret = new int[length]; int index = 0; ret[index] = temp[0]; for (int i = 1; i < ptr; i++) { if (ret[index] != temp[i]) ret[++index] = temp[i]; } return ret; } public static Method getMethod(Class clazz, String name) throws SecurityException, NoSuchMethodException { //如果是boolean的属性,必须用is方法来调用,所以先判断是否有get方法,如果没有,再判断有没有is方法 Method method = null; try { method = clazz.getMethod(buildGetMethodName(name), new Class[0]); } catch (NoSuchMethodException e) { method = clazz.getMethod(buildIsMethodName(name), new Class[0]); } return method; } public static String buildGetMethodName(String str){ StringBuffer out = new StringBuffer("get"); out.append(str.substring(0, 1).toUpperCase()).append(str.substring(1)); return out.toString(); } public static String buildIsMethodName(String str){ StringBuffer out = new StringBuffer("is"); out.append(str.substring(0, 1).toUpperCase()).append(str.substring(1)); return out.toString(); } } 6.QueryCallback:查询条件分析回调函数接口,实现对特殊查询条件的处理操作 package com.lily.dap.dao; import com.lily.dap.model.QueryExpression; /** * 查询条件分析回调函数接口,实现对特殊查询条件的处理操作,如果设置了回调接口,则系统在解析回调表达式前先调用回调接口进行解析 * * @author zouxuemo * */ public interface QueryCallback { public final static String IGRONE = "[igrone]"; /** * 分析传入的条件表达式,返回构造出的表达式,否则返回null * 如果希望查询分析器忽略表达式,则返回 IGRONE * * @param queryExpression * @return */ public String parseCondition(QueryExpression queryExpression); } 使用方式: List operationList = dao.gets(RightOperation.class, new QueryCondition() .putCondition("objectCode", permission.getRi_ob()) .putCondition("code", QueryExpression.OP_IN, new String[]{"system", "right"}) .addOrder("code").setPageSize(1).setPageNo(1)); 在我的查询条件中,如果你用的是"IN"查询,允许你传入数组或者集合进去,他会自动分析数据,构造IN的项目 |
|
返回顶楼 | |
发表时间:2006-12-13
好长啊,读完后再跟您商榷.
|
|
返回顶楼 | |
发表时间:2006-12-14
有必要拒绝SQL吗?
如果接受了关系数据库不OO的事实,请顺便也接受SQL吧。 我要写一个复杂的子查询怎么办?我要写 out join 语句怎么办 |
|
返回顶楼 | |
发表时间:2006-12-14
TO aystnd:
读完了,感觉比我想得细,也比我写得细,很好. 突然意思到一个问题,你的putCondition函数,我的RefreshCondition函数都应该加入对Sql注入攻击的防范和检测,如果发现了类似代码应该立即抛出异常退出后继执行,否则容易给客户造成不可估量的损失,那时候就麻烦大了. 如果加入后,以前对于Statement访问DB的方式的SQL不方便防范 SQL注入攻击的问题就可以写在函数内部,对外封装好以后其它程序员就不需要再考虑这个问题,这也许就是我们的代码最大价值所在,你认为呢? |
|
返回顶楼 | |
发表时间:2006-12-14
简单一点回答你:
1、SQL效率不高,不能很好的利用数据库的SQL缓冲机制, 建议改为insert dd(name) value(?) 2、如果有多表关联查询,通过这种方式拼字符方式,不好 |
|
返回顶楼 | |
发表时间:2006-12-14
对于运行时动态条件查询 可以建一个sql映射表 就像数据字典一样
根据需要从sql字典中拼装完整的sql 其实不封装更加灵活 |
|
返回顶楼 | |