`

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

阅读更多
本篇讲解“标准条件处理器”,此处理器实现了IConditionBuilder接口,此接口只有一个方法

//参数分别是属性名,属性值,POJO类,查询时的别名
public Criterion parseToCriterion(Object key, Object value, Class pojoClass, String alias);


如果要完整重写条件处理器,请实现此接口,另外下面的类的说明中还把另一种扩展方法写出来了。

标准条件得理器的完整代码

package com.esc.common.util.conditionbuilder;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Expression;
import org.hibernate.property.ChainedPropertyAccessor;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.PropertyAccessorFactory;

import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import com.esc.common.exception.BusinessException;
import com.esc.common.util.CollectionUtils;
import com.esc.common.util.Condition;
import com.esc.common.util.DetachedCriteriaUtil;
import com.esc.common.util.Operator;
import com.esc.common.util.StringUtil;
import com.esc.common.util.conditionbuilder.valuehandler.BigDecimalValueHandler;
import com.esc.common.util.conditionbuilder.valuehandler.BooleanValueHandler;
import com.esc.common.util.conditionbuilder.valuehandler.DateValueHandler;
import com.esc.common.util.conditionbuilder.valuehandler.DoubleValueHandler;
import com.esc.common.util.conditionbuilder.valuehandler.FloatValueHandler;
import com.esc.common.util.conditionbuilder.valuehandler.IValueHandler;
import com.esc.common.util.conditionbuilder.valuehandler.IntegerValueHandler;
import com.esc.common.util.conditionbuilder.valuehandler.LongValueHandler;
import com.esc.common.util.conditionbuilder.valuehandler.StringValueHandler;
import com.esc.common.util.conditionbuilder.valuehandler.TimeStampValueHandler;

/**
 * 标准的条件处理器,功能:把零散的条件属性组装成HIBERNATE能识别的Criterion对象 输入:属性名,属性值,所属性的pojo类,和别名
 * 输出:Criterion 
 * 扩展时:
 * 1、如果完整实现,只需要实现接口IConditionBuilder就行。
 * 2、如果只想另外处理某些类型的条件,如整数型条件处理器,则模仿IntegerValueHandler类再实现一个,
 *    然后通过addCustomerConditionHandlers或setCustomerConditionHandlers方法设进来就行
 * @author lgdlgd
 * 
 */
@SuppressWarnings("unchecked")
public class StandardConditionBuilder implements IConditionBuilder {
	/** 默认的各类型的条件处理器集合 */
	private Set<IValueHandler> conditionHandlers = new HashSet<IValueHandler>( 10);
	/** 用户自定义的条件处理器集合,如果默认列表中有相同类型的条件处理类,将被此集合中相同类覆盖 */
	private Set<IValueHandler> customerConditionHandlers;
	
	/** 缓存POJO类的属性访问器 */
	private Map<String, PropertyAccessor> propertyAccessors = new LinkedHashMap<String, PropertyAccessor>();

	/**
	 * 初始化的时候,把各种类型的处理器全部设入
	 * 
	 * @author lgdlgd 2009-10-13
	 */
	public StandardConditionBuilder() {
		conditionHandlers.add(StringValueHandler.getInstance());
		conditionHandlers.add(DoubleValueHandler.getInstance());
		conditionHandlers.add(LongValueHandler.getInstance());
		conditionHandlers.add(IntegerValueHandler.getInstance());
		conditionHandlers.add(BigDecimalValueHandler.getInstance());
		conditionHandlers.add(DateValueHandler.getInstance());
		conditionHandlers.add(TimeStampValueHandler.getInstance());
		conditionHandlers.add(FloatValueHandler.getInstance());
		conditionHandlers.add(BooleanValueHandler.getInstance());
	}

	/**
	 * 把字符串条件解析成condition对象,再解析成Criterion对象 此方法不支持POJO中子集合为MAP类型的查询 2008-10-16
	 * 
	 * @author lgdlgd
	 * @param key
	 * @param value
	 * @param pojoClass
	 */
	@Override
	public Criterion parseToCriterion(Object key, Object value,
			Class pojoClass, String alias) {
		try {
			return getCriterion(key.toString(), value, getPropertyType(
					pojoClass, key.toString().trim()), alias);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(), e);
		}
	}

	// ////////////以下三个方法用于递归取得POJO类中的属性的类型////////////////////////
	private Type getPropertyGenericReturnType(Class rootClass,
			String propertyName) {
		PropertyAccessor propertyAccessor = propertyAccessors.get(rootClass
				.getName());
		if (propertyAccessor == null) {
			propertyAccessor = new ChainedPropertyAccessor(
					new PropertyAccessor[] {
							PropertyAccessorFactory.getPropertyAccessor(
									rootClass, null),
							PropertyAccessorFactory
									.getPropertyAccessor("field") });
			propertyAccessors.put(rootClass.getName(), propertyAccessor);
		}
		return propertyAccessor.getGetter(rootClass, propertyName).getMethod()
				.getGenericReturnType();
	}

	private Class getPropertyType(Class rootClass, String propertyName)
			throws SecurityException, NoSuchFieldException {
		Type result = null;
		if (propertyName.contains(".")) {
			result = getPropertyType(rootClass, propertyName.split("\\."), 0);
		} else {
			result = getPropertyGenericReturnType(rootClass, propertyName);
		}
		if (result instanceof ParameterizedTypeImpl) {
			throw new BusinessException("属性" + propertyName
					+ "未明确指定集合中元素的属性名,无法进行拼装条件");
		}

		if (!(result instanceof Class)) {
			throw new BusinessException("属性" + propertyName + "为不合法的类型:"
					+ result + ",无法进行拼装条件");
		}

		return (Class) result;
	}

	private Class getPropertyType(Class rootClass, String[] propertyNames,
			int index) throws SecurityException, NoSuchFieldException {
		Class result = null;
		if (index < propertyNames.length - 1) {
			Type genericType = getPropertyGenericReturnType(rootClass,
					propertyNames[index]);
			if (genericType instanceof ParameterizedTypeImpl) {
				result = getPropertyType(
						(Class) ((ParameterizedTypeImpl) genericType)
								.getActualTypeArguments()[0], propertyNames,
						++index);
			} else {
				result = getPropertyType((Class) genericType, propertyNames,
						++index);
			}
		} else {
			result = (Class) getPropertyGenericReturnType(rootClass,
					propertyNames[index]);
		}
		return result;
	}

	// ////////////以上三个方法用于递归取得POJO类中的属性的类型////////////////////////

	/**
	 * 把字符串条件解析成condition对象,再解析成Criterion对象
	 * 
	 * @author lgdlgd 2009-1-3
	 * @param key
	 *            属性名
	 * @param value
	 *            属性值,包含操作符的值
	 * @param valueType
	 *            属性类型
	 * @param alias
	 *            别名
	 * @return Criterion 条件对象
	 */
	protected Criterion getCriterion(String key, Object value, Class valueType,
			String alias) {
		if (value == null)
			return null;
		List<Condition> conditios = null;
		// 1、先将字符串转换成一个或多个Condition对象
		if (valueType.isAssignableFrom(String.class)) {// 属性为字符串
			// 直接创建一个LIKE的条件
			conditios = new ArrayList<Condition>(1);
			Condition condition = new Condition(key, value.toString(),
					Operator.LIKE);
			conditios.add(condition);
		} else {// 属性为其它
			// 这里有可能会返回两个Condition
			conditios = parseStringToCondition(key, value.toString());
		}
		if (CollectionUtils.isEmpty(conditios))
			return null;
		// 2、 取得所有类型条件处理器,通过它将Condition对象集合转换成Criterion对象
		Set<IValueHandler> temp = getConditionHandlers();
		for (IValueHandler handler : temp) {
			if (valueType.isAssignableFrom(handler.getDealType())) {
				// 最终通过此方法返回一个HIBERNATE的Criterion对象
				return assembleToOne(handler.getConditions(conditios, alias));
			}
		}
		throw new BusinessException("找不到匹配的条件处理类,无法过滤此属性,请定义此类型的条件处理类,条件类型:"
				+ valueType.getName());
	}

	/**
	 * 把多个条件用and组成一个
	 * 
	 * @author lgdlgd 2009-1-2
	 * @param criterions
	 * @return
	 */
	private Criterion assembleToOne(List<Criterion> criterions) {
		if (criterions == null)
			return null;
		Criterion result = null;
		for (Criterion criterion : criterions) {
			if (result == null) {
				result = criterion;
			} else {
				result = Expression.and(result, criterion);
			}
		}
		return result;
	}

	/**
	 * 字符串中只允许有<和<=号 2008-10-15 把字符串条件解析成CONDITION对象
	 * 
	 * @author lgdlgd
	 * @param key
	 * @param value
	 * @return
	 */
	private static List<Condition> parseStringToCondition(String key,
			String value) {
		if (StringUtil.isEmpty(value))
			return null;

		List<Condition> conditions = new ArrayList<Condition>(5);
		String valueTemp = value.trim();
		int srcLength = value.length();
		int trimLength = valueTemp.length();

		if (trimLength != srcLength) {// 前或者有空格,要进一步检查是否有 aaa <= x <= 或者 <= x
										// <= aaa的情况
			if (trimLength == 0) {
				return null;
			}
			if (valueTemp.substring(0, 1).equals("<")) {// 属 <= x <= aaa的情况
				// 把前面截断
				value = value.substring(value
						.indexOf(DetachedCriteriaUtil.MIDDLE_SEPRATOR_CHAR),
						srcLength);
			} else if (valueTemp.substring(trimLength - 1, trimLength).equals(
					"<")
					|| valueTemp.substring(trimLength - 1, trimLength).equals(
							"=")) {// 属 aaa <= x <= 的情况
				// 把后面截断
				value = value.substring(0, value.indexOf(DetachedCriteriaUtil.MIDDLE_SEPRATOR_CHAR) + 1);
			}
		}

		if (value.trim().indexOf(DetachedCriteriaUtil.SEPARATOR_TWO_SPACE) != -1) {// 多条件,也可能是有操作符的单条件
			String[] split = value.trim().split(
					DetachedCriteriaUtil.SEPARATOR_TWO_SPACE);
			if (split.length == 3) {// 类似于 值 <= x 或 x <= 值的表达式
				boolean xPosition = split[0]
						.equalsIgnoreCase(DetachedCriteriaUtil.MIDDLE_SEPRATOR_CHAR);
				if (xPosition) {// x <= 值
					Condition condition = new Condition(key, split[2], split[1]);
					conditions.add(condition);
				} else { // 值 <= x
					if (split[1].equals("<")) {// 小于
						Condition condition = new Condition(key, split[0],
								Operator.GT);
						conditions.add(condition);
					} else {// 小于等于
						Condition condition = new Condition(key, split[0],
								Operator.GE);
						conditions.add(condition);
					}
				}

			} else if (split.length == 5) {// 类似于 值1 <= x <= 值2 的表达式
				// 把 值1 <= x 这部份拼成条件
				if (split[1].equals("<")) {
					Condition condition = new Condition(key, split[0],
							Operator.GT);
					conditions.add(condition);
				} else {
					Condition condition = new Condition(key, split[0],
							Operator.GE);
					conditions.add(condition);
				}
				// 把 x <= 值2 这部份拼成条件
				Condition condition = new Condition(key, split[4], split[3]);
				conditions.add(condition);
			}
		} else {// 单条件,无操作符
			Condition condition = new Condition(key, value);
			conditions.add(condition);
		}

		return conditions;
	}

	/**
	 * 获得所有条件组合器
	 * 
	 * @author lgdlgd 2009-1-3
	 * @return
	 */
	protected Set<IValueHandler> getConditionHandlers() {
		if (CollectionUtils.hasNotNullElement(customerConditionHandlers)) {
			conditionHandlers.addAll(customerConditionHandlers);
		}
		return conditionHandlers;
	}

	////////////////////下面两个方法是预留给用扩展某些类型的条件处理器用的///////////////
	/**
	 * 单个增加条件得处器集合
	 * @author lgdlgd
	 * 2009-10-13
	 * @param handler
	 */
	public void addCustomerConditionHandlers(IValueHandler handler) {
		if(handler==null){
			throw new BusinessException("传入条件处理器为空。");
		}
		if(customerConditionHandlers==null){
			customerConditionHandlers = new HashSet<IValueHandler>(1);;
		}
		customerConditionHandlers.add(handler);
	}

	/**
	 * 传入用户自定义条件处理器集合
	 * @author lgdlgd
	 * 2009-10-13
	 * @param customerConditionDealers
	 */
	public void setCustomerConditionHandlers(
			Set<IValueHandler> customerConditionDealers) {
		this.customerConditionHandlers = customerConditionDealers;
	}
	////////////////////上面两个方法是预留给用户扩展某些类型的条件处理器用的///////////////
}



本类构造函数中初始化所有默认的基本类型的值处理器,所有类型的条件最终是通过它们拼装成Criterion对象的,下一篇讲解这些具体类型处理器类。

2
0
分享到:
评论

相关推荐

    基于JavaEE的快速开发框架

    Hibernate是后来又补上的,最早的版本没有是因为第一个版本是为游戏服务器架构的,唯快不破的准则放弃了Hibernate,而后面增加回来是基于后台管理功能的需要。这一过程纠正了我一个开发框架中只能存在一个ORM的想法...

    基于 JavaEE 的快速开发框架 Tephra-JavaEE

    Tephra旨在构建一个稳定、高效、易于集群、快速扩展的JavaEE开发框架。目前,Tephra已经具备了以下特性: 提供类级别的热更新,但仅建议在需要快速修正严重BUG、并且无法立即进行全更新时使用。 提供全冗余方式的...

    BeetlSQL数据库访问框架是一个全功能 DAO 工具,同时具有 Hibernate.rar

    BeetSql是一个全功能DAO工具,同时具有Hibernate 优点 & Mybatis优点功能,适用于承认以SQL为中心,同时又需求工具能自动能生成大量常用的SQL的应用。 在开发效率上,无需注解,自动使用大量内置SQL,轻易完成增删...

    基于SSH框架的BBS论坛JavaEE项目源码

    10、最近登录过(三天,一周、一个月、三个月、半年)查询 11、类似微信团队号(与用户沟通账户以及推送系统消息) 12、QQ登录 jeebbsV4.0修复以及完善部分 1.权限的访问的地址链接 2.图片太大显示不全问题 3....

    Java的学习之路,学习JavaEE以及框架时候的一些项目,结合博客和源码,让你受益匪浅,适合Java初学者和刚入门开始学框架者

    [Spring]基于Spring框架的Web应用演示(附带cglib工具进行动态代理) [Tomcat7.0]Tomcat7版本安装包 [UltraISO]制作U盘启动盘需要的 [log4j_jar]log4j的支持包 [myAutoLoginWeb]过滤器Filter学习-实现用户的自动...

    基于JavaWEB+SSM+mysql框架构建的在线商城系统源码+数据库+项目说明(课程设计).zip

    本项目实现了通用 Mapper,免写 SQL,全自动处理关联查询。通过合理配置 MyBatis Generator 和自定义插件,灵活隔离手写代码和自动生成代码。实现了 BaseService 类对 Service 层进行抽象。通过拦截器实现了方法级...

    OA办公自动化管理系统(Struts1.2+Hibernate3.0+Spring2+DWR).rar

    SpringBoot 毕业设计,SpringBoot 课程设计,基于SpringBoot+Vue开发的,含有代码注释,新手也可看懂。ssm整合开发,小程序毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:...

    SSM整合.zip

    mybatis它是轻量级持久层框架,由ibatis演化而来。它完成将数据库的结果集封装到对象中POJO。业务层控制层和使用Hibernate框架一样。Hibernate基于hql是完全...全自动ORM。Mybatis基于sql是半面向对象。半自动的ORM。

    基于SSH的自助纳税申报系统【项目源码+数据库脚本】(毕设)

    ​后台框架:Spring、Struts2、Hibernate ​数据库:MySQL 开发环境:JDK、Eclipse、Tomcat 三、系统功能 本自动纳税申报系统将功能模块分为管理员功能模块和用户功能模块两个模块,接下来对这两个模块进行展开论述...

    TCCMS开源系统 v3.1

    内核借鉴了java中的struts和hibernate框架的一些思路,结合smarty MVC引擎自主研发的一套php ORM 框架。是一套高效,安全,开源的内容管理系统。 TCCMS 虽然功能不是最丰富的,可是是最实用的。最终目的是满足大...

    java web技术开发大全(最全最新)

    《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》通过对SSH中的各种技术循序渐进地讲解,使读者尽快掌握开发基于SSH的Web程序的方法。《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+...

    mysql spring c3p0/dbcp/dbUtils工具支持包

    [Spring]基于Spring框架的Web应用演示(附带cglib工具进行动态代理) [Tomcat7.0]Tomcat7版本安装包 [UltraISO]制作U盘启动盘需要的 [log4j_jar]log4j的支持包 [myAutoLoginWeb]过滤器Filter学习-实现用户的自动登录与...

    Spring面试题

    2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作 3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。 4. hibernate的性能非常好,因为它是个...

    基于SSH的教材订购管理系统【项目源码+数据库脚本】(毕设)

    ​后台框架:Spring、Struts2、Hibernate ​数据库:MySQL 开发环境:JDK、Eclipse、Tomcat 三、系统功能 该系统的功能模块包括:教材征订模块、教材管理模块、教材领用模块、系统设置模块。 1.教材征订模块 教材...

    JSP基于SSH2网上书店购物网站-毕业设计-课程设计

    用了技术框架: HTML+CSS+JavaScript+jsp+mysql+Struts2+Spring+Hibernate --- 界面美观,功能齐全,适合用作毕业设计、课程设计作业等,项目均经过测试,可快速部署运行! 1、该资源内项目代码都经过测试运行成功...

    topJava:使用Java开发具有基于角色的授权和许可的功能齐全的Spring JPA Enterprise应用程序

    Java企业在线项目Java企业最需要的技术/工具/框架:Maven / Spring /安全性/ JPA(Hibernate)/ REST(杰克逊)/ Bootstrap(CSS)/ jQuery +插件。01.28:项目开始开始检查02.02交付HW0的截止日期04.02:第一堂课...

    最新最全的spring开发包

     这个jar文件包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。 (12) spring-webmvc.jar 这个...

    Spring.3.x企业应用开发实战(完整版).part2

    10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 特殊方法成漏网之鱼 10.6.1 哪些方法不能实施Spring AOP事务 10.6.2 事务增强遗漏实例 10.7 数据连接泄漏 10.7.1 底层连接资源的访问问题 10.7.2 Spring JDBC...

    Spring3.x企业应用开发实战(完整版) part1

    10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 特殊方法成漏网之鱼 10.6.1 哪些方法不能实施Spring AOP事务 10.6.2 事务增强遗漏实例 10.7 数据连接泄漏 10.7.1 底层连接资源的访问问题 10.7.2 Spring JDBC...

Global site tag (gtag.js) - Google Analytics