- 浏览: 22990 次
- 性别:
- 来自: 上海
最新评论
-
ls_autoction:
你写非常独到的地方,是我查过百度,Google中最难懂的地方, ...
dojo中的grid的改进 -
晨曦的朝阳:
刚刚出炉的国产jquery-ui开源组件库 http://ui ...
用dojo做web前端的思考 -
bluseli:
你好,正在研究activemq中。看了你的文章。非常好。
希望 ...
一个多线程的服务器例子 -
fffddd:
不见得吧。贴出执行计划来看看。
大量数据时,SQL语句的书写区别 -
duooluu:
一眼看不完你的SQL
为了说明问题还是精简掉一些字段为好
大量数据时,SQL语句的书写区别
在开发web应用程序中,表单查询是一个非常常见的功能,但是需求五花八门,各种各样,更重要的是,后端的SQL/hql要根据页面的输入动态变化。常常形成一个庞大的拼sql的方法,并且各个方法都不一样,为开发,维护带来了不少困难。本人在总结了常用需求的基础上,再结合SSH,想出一个比较通用的方案,以此抛砖引玉。
实现的思路是这样的,根据页面输入,自动将页面输入转化成一组查询条件,数据访问层再根据这些查询条件自动组装SQL/hql。这个是查询条件类。
import java.io.Serializable; /** * 表单上的查询条件封装类 * 封装表单的查询条件 * * @auther: XXX * Date: 11-4-22 * Time: 下午2:16 * @version: 1.0 */ public class QueryCondition implements Serializable { /** * 查询主实体名称 */ private String enityName; /** * 实体对应的属性名称 */ private String propertyName; /** * 实体对应的属性类型 */ private String propertyType; /** * 查询关系符号 */ private Operator operator; /** * like查询时候的匹配模式 */ private MatchMode matchMode; /** * 条件的值 */ private String value; /** * 输入的第二个值 */ private String value2; /** * 多个值 */ private String[] multipleValue; public MatchMode getMatchMode() { return matchMode; } public void setMatchMode(MatchMode matchMode) { this.matchMode = matchMode; } public String getEnityName() { return enityName; } public void setEnityName(String enityName) { this.enityName = enityName; } public String getPropertyName() { return propertyName; } public void setPropertyName(String propertyName) { this.propertyName = propertyName; } public String getPropertyType() { return propertyType; } public void setPropertyType(String propertyType) { this.propertyType = propertyType; } public Operator getOperator() { return operator; } public void setOperator(Operator operator) { this.operator = operator; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getValue2() { return value2; } public void setValue2(String value2) { this.value2 = value2; } public String[] getMultipleValue() { return multipleValue; } public void setMultipleValue(String[] multipleValue) { this.multipleValue = multipleValue; } }
这个是oprator类,包含了常用的操作符
/** * 关系操作符号 * * @author XX * @version 1.0 */ public enum Operator { LIKE, // Like LT, // 小于 GT, // 大于 LE, // 小于等于 GE, // 大于等于 NE, // 不等于 IN, // IN BETWEEN, //between EQ //等于 }
MathcMode 匹配模式类,模仿hibernate
/** * @auther: XXX * Date: 11-4-27 * Time: 下午4:40 * @version: 1.0 */ public enum MatchMode { //精确匹配 EXACT, BEFORE,//前匹配 AFTER, //后匹配 ANYWHERE //任意匹配 }
根据查询条件构造criteria
/** * 根据查询条件组件 QueryBuilder * QueryBuilder 的用法请参考hibernate源代码 * * @param conditions 查询条件 * @return */ protected Criteria buildCritria(final List<QueryCondition> conditions) { if (conditions != null && conditions.size() > 0) { Criteria criteria = getSession().createCriteria(entityClass); ClassMetadata metadata = getSessionFactory().getClassMetadata(entityClass); for (QueryCondition qc : conditions) { if (qc == null) continue; Type type = metadata.getPropertyType(qc.getPropertyName()); switch (qc.getOperator()) { case LIKE: if (StringUtils.isNotEmpty(qc.getValue())) { switch (qc.getMatchMode()) { case EXACT: criteria.add(Restrictions.like(qc.getPropertyName(), qc.getValue(), MatchMode.EXACT)); break; case AFTER: criteria.add(Restrictions.like(qc.getPropertyName(), qc.getValue(), MatchMode.END)); break; case BEFORE: criteria.add(Restrictions.like(qc.getPropertyName(), qc.getValue(), MatchMode.START)); break; case ANYWHERE: criteria.add(Restrictions.like(qc.getPropertyName(), qc.getValue(), MatchMode.ANYWHERE)); break; default: criteria.add(Restrictions.like(qc.getPropertyName(), qc.getValue(), MatchMode.ANYWHERE)); break; } } break; case LT: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); criteria.add(Restrictions.lt(qc.getPropertyName(), value)); } break; case GT: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); criteria.add(Restrictions.gt(qc.getPropertyName(), value)); } break; case LE: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); criteria.add(Restrictions.le(qc.getPropertyName(), value)); } break; case GE: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); criteria.add(Restrictions.ge(qc.getPropertyName(), value)); } break; case NE: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); criteria.add(Restrictions.ne(qc.getPropertyName(), value)); } break; case IN: if (qc.getMultipleValue() != null && qc.getMultipleValue().length > 0) { Object[] values = new Object[qc.getMultipleValue().length]; for (int i = 0; i < qc.getMultipleValue().length; i++) { values[i] = stringToObject(qc.getMultipleValue()[i], type); } criteria.add(Restrictions.in(qc.getPropertyName(), values)); } break; case BETWEEN: if (StringUtils.isNotEmpty(qc.getValue()) || StringUtils.isNotEmpty(qc.getValue2())) { criteria.add(Restrictions.between(qc.getPropertyName(), qc.getValue(), qc.getValue2())); } break; default: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); criteria.add(Restrictions.eq(qc.getPropertyName(), value)); } break; } } return criteria; } return null; }
根据查询条件构造hql
/** * 根据查询条件组件 QueryBuilder * QueryBuilder 的用法请参考hibernate源代码 * * @param conditions 查询条件 * @return */ protected QueryBuilder buildQuery(final List<QueryCondition> conditions) { if (conditions != null && conditions.size() > 0) { String entityName = entityClass.getSimpleName(); QueryBuilder queryBuilder = new QueryBuilder(entityName, StringUtils.uncapitalize(entityName)); ClassMetadata metadata = getSessionFactory().getClassMetadata(entityClass); Parameters parameters = queryBuilder.getRootParameters(); for (QueryCondition qc : conditions) { if (qc == null) continue; Type type = metadata.getPropertyType(qc.getPropertyName()); switch (qc.getOperator()) { case LIKE: if (StringUtils.isNotEmpty(qc.getValue())) { String value = qc.getValue(); switch (qc.getMatchMode()) { case EXACT: break; case BEFORE: value = "%" + value; break; case AFTER: value = value + "%"; break; case ANYWHERE: value = "%" + value + "%"; break; default: value = "%" + value + "%"; break; } parameters.addWhereWithParam(qc.getPropertyName(), "like", value); } break; case LT: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); parameters.addWhereWithParam(qc.getPropertyName(), "<", value); } break; case GT: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); parameters.addWhereWithParam(qc.getPropertyName(), ">", value); } break; case LE: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); parameters.addWhereWithParam(qc.getPropertyName(), "<=", value); } break; case GE: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); parameters.addWhereWithParam(qc.getPropertyName(), ">=", value); } break; case NE: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); parameters.addWhereWithParam(qc.getPropertyName(), "!=", value); } break; case IN: if (qc.getMultipleValue() != null && qc.getMultipleValue().length > 0) { Object[] values = new Object[qc.getMultipleValue().length]; for (int i = 0; i < qc.getMultipleValue().length; i++) { values[i] = stringToObject(qc.getMultipleValue()[i], type); } parameters.addWhereWithParams(qc.getPropertyName(), "in (", values, ")"); } break; case BETWEEN: if (StringUtils.isNotEmpty(qc.getValue()) && StringUtils.isEmpty(qc.getValue2())) { Object minValue = stringToObject(qc.getValue(), type); parameters.addWhereWithParam(qc.getPropertyName(), ">=", minValue); } else if (StringUtils.isEmpty(qc.getValue()) && StringUtils.isNotEmpty(qc.getValue2())) { Object maxValue = stringToObject(qc.getValue(), type); parameters.addWhereWithParam(qc.getPropertyName(), "<=", maxValue); } else if (StringUtils.isNotEmpty(qc.getValue()) && StringUtils.isNotEmpty(qc.getValue2())) { Object minValue = stringToObject(qc.getValue(), type); Object maxValue = stringToObject(qc.getValue2(), type); parameters.addWhereWithParam(qc.getPropertyName(), ">=", minValue); parameters.addWhereWithParam(qc.getPropertyName(), "<=", maxValue); } break; default: if (StringUtils.isNotEmpty(qc.getValue())) { Object value = stringToObject(qc.getValue(), type); parameters.addWhereWithParam(qc.getPropertyName(), "=", value); } break; } } return queryBuilder; } return null; }
由于从前端传来的参数都是String型的,所以需要把String型的数据进行数据类型转换。这里借助了hibernate的实现。
/** * 从字符串到java对象的转换 * * @param value 值 * @param type 类型 * @return */ protected Object stringToObject(String value, Type type) { Object ret = null; if (type instanceof TimestampType) { SimpleDateFormat sdf = new SimpleDateFormat(); if (value.length() > 10) { sdf.applyPattern("yyyy-MM-dd HH:mm:ss"); } else { sdf.applyPattern("yyyy-MM-dd"); } try { ret = sdf.parse(value); } catch (ParseException e) { e.printStackTrace(); } } else if (type instanceof AbstractStandardBasicType) { ret = ((AbstractStandardBasicType) type).fromString(value); } return ret; }
调用方法执行
/** * 根据条件自动查询 * * @param conditions 查询条件 * @return */ public final List<T> findByCondition(final List<QueryCondition> conditions) { Criteria criteria = buildCritria(conditions); if (criteria != null) { //增加自定义的其他查询条件 addCustomCriterion(criteria); return criteria.list(); } return null; }
为了能将页面上输入值变成查询条件的List,结合了struts2的自动封装数据的特性,在html中只要这样写,就可以自动将输入项目组装成查询条件的List
<td width="9%" class="right"> 用户编号<@splitor/> </td> <td width="18%"> <input type="hidden" name="condition[0].propertyName" value="userCode"/> <select id="__select_userCode" name="condition[0].operator" dojoType="dijit.form.Select"> <option value="LIKE">模糊查询</option> <option value="EQ">相等</option> <option value="LT">小于</option> <option value="GT">大于</option> <option value="LE">小于等于</option> <option value="GE">大于等于</option> <option value="NE">不等于</option> <option value="IN">等于多个</option> <option value="BETWEEN">范围</option> </select> <input type="hidden" name="condition[0].matchMode" value="BEFORE"/> <input dojoType="dijit.form.TextBox" name="condition[0].value" id="userCode"/> </td> <td width="9%" class="right"> 名称<@splitor/> </td> <td width="18%"> <input type="hidden" name="condition[1].propertyName" value="userName"/> <select id="__select_userName" name="condition[1].operator" dojoType="dijit.form.Select"> <option value="LIKE">模糊查询</option> <option value="EQ">相等</option> <option value="LT">小于</option> <option value="GT">大于</option> <option value="LE">小于等于</option> <option value="GE">大于等于</option> <option value="NE">不等于</option> <option value="IN">等于多个</option> <option value="BETWEEN">范围</option> </select> <input type="hidden" name="condition[1].matchMode" value="ANYWHERE"/> <input dojoType="dijit.form.TextBox" name="condition[1].value" id="userName"/> </td>
只要在Action或者Model中定义这样的一个属性,就可以完成自动转换。
/** * 查询条件 */ protected List<QueryCondition> condition;
当页面提交或者ajax请求时,会自动将上面的输入变成condition,只要将condition传入上述的方法内,就会自动组装查询条件。
为了让页面书写简单,将上面的输入项目写成一个宏吧,这样使用更方便。
<#-- |查询条件 | property 属性名 必须输入的参数 | index 顺序号 可选参数,但是要保证它不重复 | id 每个输入项的Id,可选参数,但是在使用dojo的情况下,要保证它不重复 | type 输入框的类型,这个类型是指的dojo的类型。 | 大体来说分为,文本,下拉单,日期输入框,数字输入框 ,复选框,单选框 这几种 --> <#macro seniorQuery property index=0 id="id" type="text"> <label for="${id}"><@s.text name="${property}"/>:</label> <input type="hidden" name="condition[${index}].propertyName" value="${property}"/> <select id="__select_${id}" name="condition[${index}].operator" dojoType="dijit.form.Select"> <option value="LIKE">模糊查询</option> <option value="EQ">相等</option> <option value="LT">小于</option> <option value="GT">大于</option> <option value="LE">小于等于</option> <option value="GE">大于等于</option> <option value="NE">不等于</option> <option value="IN">等于多个</option> <option value="BETWEEN">范围</option> </select> <#--根据类型决定输入控件的类型--> <#local controlType = "dijit.form.TextBox"> <#if type=="number"> <#local controlType="dijit.form.NumberTextBox"> <#elseif type="date"> <#local controlType="dijit.form.DateTextBox"> <#elseif type="combo"> <#local controlType="dojo.form.ComboBox"> <#elseif type="checkbox"> <#local controlType="dojo.form.CheckBox"> <#elseif type="radio"> <#local controlType="dojo.form.Radio"> </#if> <input id="${id}" name="condition[${index}].value" dojoType="${controlType}"/> <script type="text/javascript"> dojo.ready(function() { dojo.connect(dijit.byId("__select_${id}"), "onChange", function() { var operator = dijit.byId("__select_${id}").value; if (operator == "BETWEEN") { var newObj = new ${controlType}({ id:"${id}Max", name:"condition[${index}].value2"}); newObj.placeAt(dijit.byId("${id}").domNode, "after"); } else { if (typeof(dijit.byId("${id}Max")) != "undefined") { dijit.byId("${id}Max").destroy(); } } }); }) </script> </#macro>
这样使用起来更方便,你的查询方法会更容易维护,因为所有 表单的查询条件,都被自动创建为criteria了,额外的关联你可以在addCustomCriterion(criteria);里面实现,这个方法是空方法,你只要新建一个子类,重写此方法就可以了。
当然你可以扩展这些宏,或者这些方法。
相关推荐
在传统的Web应用中,当用户在表单中输入查询条件或翻页时,页面会通过HTTP请求发送到服务器,服务器处理请求,然后返回新的HTML页面。这种方式效率较低,因为每次交互都需要完整页面的刷新。然而,通过前端分页和...
在Web开发领域,创建一个应用应聘表单是常见的任务,尤其在招聘流程自动化的过程中。"应用Web应聘表单"是一个用于收集求职者信息的在线平台,它具备信息验证功能、日期选择器以及二级省市联动菜单,以确保提交的数据...
Infopath是一个由微软开发的信息收集工具,主要用于设计、发布和管理XML表单,它允许用户无需编程就可以创建复杂的表单,并且能够将这些表单部署为基于Web的应用程序。Infopath表单通常在Microsoft Office InfoPath ...
通过理解两者之间的转换机制和Domino Designer的特性,开发者可以创建出满足不同需求的Web应用程序,同时确保数据的准确性和用户界面的友好性。在实际开发过程中,不断探索和实践这些知识点,将有助于提升Web应用的...
移动Web应用程序组建是针对ASP.NET框架的一个重要工具集,它专为在移动设备上构建高效、响应式的Web应用而设计。这些组件和技术使得开发者能够利用ASP.NET的优势,为智能手机和平板电脑等移动设备提供优化的用户体验...
但是,根据标题、描述和标签,可以推测本书的内容涉及C#语言和Web应用程序的入门知识。 C#是一种面向对象的编程语言,它是微软公司推出的一种高级编程语言,主要运行于.NET框架之上。C#具备了现代编程语言所需的...
总之,掌握Web表单的高级技巧对于提升Web应用程序的质量和用户满意度至关重要。通过优化表单设计、高效处理表单数据以及利用ASP.NET的特性,我们可以创建更加智能和用户友好的Web表单。不断学习和实践,才能在这个...
《C# Web开发者指南教程》是一本专门为初学者设计的教育资源,旨在帮助读者掌握使用C#语言进行Web应用程序开发的基本技能。这本书包含了丰富的理论知识和实际操作指导,结合了源代码,使得学习过程更具实践性。 C#...
在 WEB 应用程序中,表单是必不可少的一部分,例如注册、登录、支付等,它们直接影响着用户体验和网站的整体性能。然而,填写表单通常是件麻烦的事情,人们总是希望快速完成表单,以便继续下一步的操作。因此,设计...
总而言之,Web表单设计对于网站和应用程序来说至关重要,因为它们直接涉及到用户交互和数据收集的过程。一个设计良好的表单可以提高用户体验,促进信息的有效获取,并且有助于提升网站的整体可用性。本书通过深入...
通过这个自定义表单Web工程,我们可以学习到如何结合Java后端技术和前端技术来实现一个完整的Web应用,理解服务器与浏览器之间的通信过程,以及如何利用现有的开发工具和框架提高开发效率。同时,对于想要深入学习...
Java Web 应用开发实用教程习题答案 本资源总结了《Java Web 应用开发实用教程》的习题答案,涵盖了 HTML、Java Web 开发、JSP、Tomcat 等方面的知识点。 一、HTML 基础知识 1. HTML 中超链接标记为 `和</a>` 2. ...
**Flask Web开发:基于Python的Web应用开发实战** Flask是Python编程语言中的一个轻量级Web应用程序框架,以其简洁、灵活的特性受到了开发者们的广泛欢迎。它遵循"微框架"理念,允许开发者自由选择如何组织项目和...
通过本教程的学习,你将具备开发动态、功能丰富的Web应用的能力,同时也能为进阶学习如框架、前端技术、服务器优化等打下坚实的基础。在实践中不断探索和积累经验,你将成为一名出色的PHP开发者。
《Flask Web应用开发实战》是一本专注于使用Python的轻量级Web框架Flask进行Web应用开发的专业书籍。Flask以其简洁、灵活的特性,在Python Web开发领域深受开发者喜爱。这本书详细介绍了如何利用Flask构建功能完备的...
《Flask Web开发:基于Python的Web应用开发实战》是一本深入浅出的教程,旨在帮助读者掌握使用Python的Flask框架构建Web应用程序的技术。Flask是一个轻量级的Web服务器网关接口(WSGI)Web应用框架,以其灵活性、...
根据给定的文件信息,我们可以深入探讨Web应用程序框架组件及其在构建现代Web应用中的关键作用。这份《Web应用程序框架组件参考指南》不仅是一份技术文档,更是开发人员理解和掌握Web应用构建基石的重要资料。 ### ...
1. **表单验证**:在Web应用中,用户输入的数据需要进行验证,以确保其有效性和安全性。这通常通过JavaScript或jQuery实现,例如检查电子邮件格式、手机号码合法性等。同时,后台也可以通过Servlet或JSP进行二次验证...
《Java Web应用开发项目教程》是一本以实践为导向的教程,旨在帮助读者深入理解并掌握Java Web开发技术。教程通过完整的案例,采用模块化的教学方式,将复杂的Web应用开发过程分解为可操作的步骤,逐步引导学习者...