首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

基于HIBERNATE的全自动查询框架(4)

2012-11-04 
基于HIBERNATE的全自动查询框架(四)这是全自动查框架最后一篇,主要讲解上一篇中最后提到的各种类型的值的

基于HIBERNATE的全自动查询框架(四)
这是全自动查框架最后一篇,主要讲解上一篇中最后提到的各种类型的值的处理器,这些处理器最终将:
    对字符串继使用LIKE关键字,
    对日期分拆成两个日期:当天的0时0分0秒和23时59分59秒,使用>=日期1并且<=日期二
    对两个日期,直接使用>=日期1并且<=日期二
    对单个数字,使用=
    对两个数字,使用>=日期1并且<=日期二
    对于其它类其它类型,如Boolean使用=
生成最终HIBERNATE能接受的Criterion对象。类图如下


接口的完成代码

package com.esc.common.util.conditionbuilder.valuehandler;import java.util.List;import org.hibernate.criterion.Criterion;import com.esc.common.util.Condition;/** * 条件处理器接口 */public interface IValueHandler {/** * 把condition对象转换Hibernate能识别的条件对象 * @param conditios * @param alias * @return */List<Criterion> getConditions(List<Condition> conditios, String alias);/** * 获得本处理器能处理的属性类型 * @return 本处理器能处理的属性类型 */Class getDealType();}


抽象类代码如下
package com.esc.common.util.conditionbuilder.valuehandler;import java.util.ArrayList;import java.util.List;import org.hibernate.criterion.Criterion;import org.hibernate.criterion.Expression;import org.hibernate.criterion.MatchMode;import com.esc.common.util.Condition;import com.esc.common.util.DetachedCriteriaUtil;import com.esc.common.util.Operator;/** * 拼条件基类 */public abstract class AbstractValueHandler implements IValueHandler {//取得别名private String getColumnAlia(String columName,String alias){if(columName.contains(".")){return DetachedCriteriaUtil.getAliasFromPropertyChainString(columName);}return new StringBuffer().append(alias).append(".").append(columName).toString();}//构造=条件protected Criterion eq(String key,Object value, String alias) {return Expression.eq(getColumnAlia(key,alias), value);}//构造<=条件protected Criterion le(String key,Object value, String alias) {return Expression.le(getColumnAlia(key,alias), value);}//>=protected Criterion ge(String key,Object value, String alias) {return Expression.ge(getColumnAlia(key,alias), value);}//<protected Criterion lt(String key,Object value, String alias) {return Expression.lt(getColumnAlia(key,alias), value);}//>protected Criterion gt(String key,Object value, String alias) {return Expression.gt(getColumnAlia(key,alias), value);}//likeprotected Criterion like(String key,Object value, String alias) {return Expression.like(getColumnAlia(key,alias), value.toString(),MatchMode.ANYWHERE).ignoreCase();}/** * 抽象类已实现了接口的第一个方法 * 真正拼条件的方法 * @param conditios */@Overridepublic List<Criterion> getConditions(List<Condition> conditios,String alias) {//第一步调用具体子类,子类先把条件值从字符串转换成各种类型的值,把一个日期分拆成两个日期等,是由具体子类做的事beforeDoAdd(conditios);//子类把结果放回到集合,这里可以循环的取出单个Condition对象,生成Criterion对象了List<Criterion> result = new ArrayList<Criterion>(conditios.size());if (conditios.size() == 1) {//单条件Condition condition = conditios.get(0);if(condition.getValue() instanceof String){//处理字符串,目前字符串只支持单条件,即不支持 like xxx or like yyyresult.add(like(condition.getProperty(), condition.getValue(),alias));}else{//处理其它类型if (Operator.EQ.equals(condition.getOperator())){result.add(eq(condition.getProperty(), condition.getValue(),alias));} else if (Operator.GT.equals(condition.getOperator())) {result.add(gt(condition.getProperty(), condition.getValue(),alias));} else if (Operator.LE.equals(condition.getOperator())) {result.add(le(condition.getProperty(), condition.getValue(),alias));} else if (Operator.LT.equals(condition.getOperator())) {result.add(lt(condition.getProperty(), condition.getValue(),alias));} else if (Operator.GE.equals(condition.getOperator())) {result.add(ge(condition.getProperty(), condition.getValue(),alias));}}} else {//多条件,如 aaa  <  x  <   bbbfor (Condition condition : conditios) {if (Operator.GE.equals(condition.getOperator())) {result.add(ge(condition.getProperty(), condition.getValue(),alias));} else if (Operator.GT.equals(condition.getOperator())) {result.add(gt(condition.getProperty(), condition.getValue(),alias));} else if (Operator.LE.equals(condition.getOperator())) {result.add(le(condition.getProperty(), condition.getValue(),alias));} else if (Operator.LT.equals(condition.getOperator())) {result.add(lt(condition.getProperty(), condition.getValue(),alias));}}}return result;}/** * 此方法主要是把Condition中的VALUE值转成所需类型,修正日期格式和时间值,把一个日期分拆成两个日期等 * @param conditios */protected abstract void beforeDoAdd(List<Condition> conditios);@Overridepublic boolean equals(Object obj) {if(!(obj instanceof IValueHandler))return false;return ((IValueHandler)obj).getDealType().getName().equals(getDealType().getName());}@Overridepublic int hashCode() {return getDealType().getName().hashCode();}protected int getYearFromDateString(String dateString){return Integer.valueOf(dateString.substring(0,4));}protected int getMonthFromDateString(String dateString){return Integer.valueOf(dateString.substring(4,6));}protected int getDayFromDateString(String dateString){return Integer.valueOf(dateString.substring(6,8));}}


主要的逻辑其实就在于上面这个抽象类,具体子类的代码一般很少,下面首先是处理字符串类型的子类的代码:
package com.esc.common.util.conditionbuilder.valuehandler;import java.util.List;import com.esc.common.util.Condition;public class StringValueHandler extends AbstractValueHandler {private static StringValueHandler stringConditionDealer = new StringValueHandler();private StringValueHandler(){super();}//实现父类定义的回调方法,在父类拼条件前将条件值中的空格替换成%,@Overrideprotected void beforeDoAdd(List<Condition> conditios) {Condition condition = conditios.get(0);condition.setValue(condition.getValue().toString().replaceAll(" ", "%"));}//返回本类所能处理的条件类型@Overridepublic Class getDealType() {return String.class;}public static IValueHandler getInstance() {return stringConditionDealer;}}


处理整形数字的类
package com.esc.common.util.conditionbuilder.valuehandler;import java.util.List;import com.esc.common.util.Condition;public class IntegerValueHandler extends AbstractValueHandler {private static IntegerValueHandler integerConditionDealer = new IntegerValueHandler();private IntegerValueHandler(){super();}public static IValueHandler getInstance() {return integerConditionDealer;}//将字符串传换成整形数字@Overridepublic void beforeDoAdd(List<Condition> conditios) {for (Condition condition : conditios) {condition.setValue(new Integer(condition.getValue().toString()));}}//本类处理整形条件@Overridepublic Class getDealType() {return Integer.class;}}


其它如长整型,浮点型的代码都差一多,只有处理日期的比较复杂,要分析不同格式的日期,并决定是否将一个值拆分成两个,下面是TimeStampValueHandler类的代码
package com.esc.common.util.conditionbuilder.valuehandler;import java.sql.Timestamp;import java.util.GregorianCalendar;import java.util.List;import com.esc.common.exception.BusinessException;import com.esc.common.util.Condition;import com.esc.common.util.DateUtil;import com.esc.common.util.Operator;public class TimeStampValueHandler extends AbstractValueHandler {private static String CURRECT_DATE_FORMATE = " 正确的格式有:年-2009、 年月-200903、 年月日-20090328、年月日时分秒-20090328230159";private static TimeStampValueHandler stringConditionBuilder = new TimeStampValueHandler();private TimeStampValueHandler() {super();}public static TimeStampValueHandler getInstance() {return stringConditionBuilder;}@SuppressWarnings("deprecation")@Overridepublic void beforeDoAdd(List<Condition> conditios) {int conditionCount = conditios.size();if (conditionCount == 2) {// 有两个条件for (int i = 0; i < conditionCount; i++) {Condition condition = conditios.get(i);if (i == 0) {// 处理第一个条件handleFirstCondition(condition);} else {// 处理第二个条件handleSecondCondition(condition);}}} else if(conditionCount == 1){//只有一个条件,加一条件后递归Condition condition = conditios.get(0);if(condition.getOperator().equals(Operator.EQ)){//把条件变成大于等于condition.setOperator(Operator.GE);//新增一个小于的条件Condition condition2 = new Condition(condition.getProperty(),condition.getValue(),Operator.LT);conditios.add(condition2);beforeDoAdd(conditios);}else{handleFirstCondition(condition);}}}private void handleFirstCondition(Condition condition){Timestamp date = null;// 去除分隔符,前一个冒号是全角,后一个是半角String value = cutChars(condition.getValue().toString());int dateLength = value.length();switch (dateLength) {case 14://精确到秒,直接取当秒的0毫秒0微秒date = new Timestamp(DateUtil.convertStringToDate("yyyyMMddHHmmss", value).getTime());break;case 8://精确到天,取当天0时0分0秒date = new Timestamp(DateUtil.convertStringToDate("yyyyMMdd", value).getTime());break;case 6://精确到月,取当前1号0时0分0秒date = new Timestamp(new GregorianCalendar(getYearFromDateString(value),getMonthFromDateString(value) - 1, 1).getTimeInMillis());break;case 4://精确到年,取当年1月1号0时,0分0秒date = new Timestamp(new GregorianCalendar(getYearFromDateString(value), 0, 1).getTimeInMillis());break;default:throw new BusinessException("您输入的时间:"+value+",格式不对"+CURRECT_DATE_FORMATE);}condition.setValue(date);}private void handleSecondCondition(Condition condition){Timestamp date = null;// 去除分隔符,前一个冒号是全角,后一个是半角String value = cutChars(condition.getValue().toString());int dateLength = value.length();switch (dateLength) {case 14://精确到秒,加999毫秒date = new Timestamp(DateUtil.convertStringToDate("yyyyMMddHHmmss", value).getTime()+999);break;case 8://精确到天,取下一天0时0分0秒再减一毫秒date = new Timestamp(new GregorianCalendar(getYearFromDateString(value),getMonthFromDateString(value)-1,getDayFromDateString(value)+1).getTimeInMillis()-1);break;case 6://精确到月,取下一月1号0时0分0秒再减一毫秒date = new Timestamp(new GregorianCalendar(getYearFromDateString(value),getMonthFromDateString(value),1).getTimeInMillis()-1);break;case 4://精确到年,取下一年1月1号0时0分0秒再减一毫秒date = new Timestamp(new GregorianCalendar(getYearFromDateString(value)+1,0,1).getTimeInMillis()-1);break;default:throw new BusinessException("时间输入格式不对:"+value+CURRECT_DATE_FORMATE);}condition.setValue(date);}private String cutChars(String src) {return src.replaceAll(":", "").replaceAll("-", "").replaceAll(":", "").replaceAll("/", "").replaceAll(" ", "");}@Overridepublic Class<Timestamp> getDealType() {return Timestamp.class;}}


其它类型的日期是委托此类完成的,如处理java.util.date类型条件的类代码
package com.esc.common.util.conditionbuilder.valuehandler;import java.util.Date;import java.util.List;import com.esc.common.util.Condition;@SuppressWarnings("unchecked")public class DateValueHandler extends AbstractValueHandler {private static DateValueHandler dateConditionBuilder = new DateValueHandler();private DateValueHandler(){super();}public static DateValueHandler getInstance() {return dateConditionBuilder;}//使用TimeStampConditionDealer来处理public void beforeDoAdd(List<Condition> conditios) {TimeStampValueHandler.getInstance().beforeDoAdd(conditios);}@SuppressWarnings("unchecked")@Overridepublic Class getDealType() {return Date.class;}}

热点排行