`

基于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
分享到:
评论

相关推荐

    基于Hibernate和SpringMVC框架的小型书店管理网站S

    【标题】:基于Hibernate和SpringMVC框架的小型书店管理网站S 【描述】:小型书店管理网站是一个常见的Web应用程序示例,它利用了Hibernate和SpringMVC这两个强大的开源框架。Hibernate是Java领域中广泛使用的对象...

    基于hibernate,spring,struts,shiro,activiti,easyui框架的物流系统,可做毕业设计

    在这个物流系统中,Hibernate用于将业务对象(如订单、货物、客户等)映射到数据库表,通过SQL查询操作数据,而无需直接编写大量的SQL语句,提高了开发效率和代码的可维护性。 2. **Spring**:Spring是Java企业级...

    MyEclipse10+Struts2.1+Spring3.3+Hibernate3.3全注解框架搭建

    本教程将详细阐述如何利用MyEclipse10,一个强大的Java EE集成开发环境,搭建一个基于Struts2.1、Spring3.3和Hibernate3.3的全注解框架。这种框架被称为SSH2,因为它包含了Struts2、Spring和Hibernate这三大主流Java...

    OA项目struts2,spring,hibernate 三大框架

    以下将详细阐述这三个框架的核心功能和它们在OA(办公自动化)项目中的应用。 **Struts2框架** Struts2是一个基于MVC(Model-View-Controller)设计模式的Web应用框架,它主要负责控制层。Struts2通过拦截器机制...

    hibernate的文档最全版

    这个文档最全版可能涵盖了上述所有内容,以及更详细的使用示例和配置说明,帮助开发者深入理解和应用Hibernate 4.0.0 Beta5框架。通过阅读这份文档,你可以全面了解Hibernate的基础概念、配置、API使用以及最佳实践...

    基于hibernate,spring,spring mvc,bootstrap框架开发的管理系统

    《基于Hibernate,Spring,Spring MVC,Bootstrap框架的管理系统详解》 在现代企业级应用开发中,选择合适的框架能够显著提高开发效率,降低维护成本。本文将深入探讨一个基于Hibernate、Spring、Spring MVC以及...

    hibernate相关插件全集

    此外,它还可以生成基于Hibernate的DAO(数据访问对象)层,进一步提高了开发效率。 接下来是hibernate-annotations-3.3.0.GA,这是Hibernate 3.x系列的一个版本,包含了Hibernate的注解支持。在Java中,注解是一种...

    基于Struts+Hibernate的网上问卷调查系统

    基于Struts2和Hibernate的问卷调查系统通常采用三层架构设计: - **表现层(Presentation Layer)**: 由Struts2处理HTTP请求,展现用户界面。视图通常使用JSP或Freemarker模板。 - **业务逻辑层(Business Logic ...

    Struts-Spring-Hibernate三大框架整合项目——人力资源管理系统

    Struts、Spring和Hibernate是Java开发中非常流行的三大框架,它们各自解决了一部分软件开发中的问题,而将它们整合在一起可以构建出高效、模块化且易于维护的企业级应用。在这个"人力资源管理系统"项目中,我们将...

    Struts、Spring、Hibernate三大框架的原理和优点

    ### Struts、Spring、Hibernate三大框架的原理和优点 #### 1. Struts框架的原理与优点 **Struts** 是一种基于MVC(Model-View-Controller)设计模式的Web应用框架,它广泛应用于Java Web开发中。下面详细介绍...

    基于spring+springmvc+hibernate的全注解开发

    在现代Java Web开发中,Spring、SpringMVC和Hibernate是三个非常重要的框架,它们共同构建了一个强大的、灵活的和高效的应用程序开发环境。基于Spring+SpringMVC+Hibernate的全注解开发,允许开发者摆脱传统的XML...

    SSH三大框架整合 struts2+hibernate+spring (全注解方式进行配置)

    SSH是Java Web开发中的三个重要框架的简称,分别代表Struts2、Hibernate和Spring。这三大框架的整合能够实现高效、灵活的后端业务逻辑处理和数据管理。本教程将重点讲解如何使用全注解的方式来配置这三个框架,使得...

    springmvc +spring+hibernate的smart框架

    Smart框架是一种基于SpringMVC、Spring和Hibernate的整合框架,旨在简化企业级Web应用的开发工作。这个框架利用了Maven进行项目管理和构建,确保了依赖管理的有效性和一致性。通过集成这些主流的技术栈,Smart提供了...

    spring、spring mvc、hibernate、material 前端框架开发简易BBS论坛系统

    本项目是一个基于Spring、Spring MVC、Hibernate和Material前端框架构建的简单BBS论坛系统,旨在为初学者提供一个学习和实践这些技术的平台。在这个系统中,你可以看到如何将Java后端技术和现代化的前端设计结合,以...

    jsp+Struts+hibernate基本框架搭建demo

    总的来说,"jsp+Struts+hibernate基本框架搭建demo"是一个典型的Java Web应用开发实践,涵盖了前端展示、后端控制和数据库操作的全过程。通过这样的示例,开发者可以学习到如何在实际项目中有效地组织代码和配置,...

    基于全注解的SSH2框架

    **基于全注解的SSH2框架详解** SSH2框架,即Spring、Struts2和Hibernate的集成,是Java开发Web应用程序的主流框架之一。在这个基于全注解的SSH2框架中,我们将深入探讨如何利用注解来简化配置,提高开发效率,并...

    jeesite web框架hibernate+spring+shiro

    《Jeesite Web框架:Hibernate、Spring与Shiro深度整合》 Jeesite是一个开源的Java Web框架,它集成了Hibernate、Spring和Shiro等组件,构建了一个强大的企业级应用开发平台。这篇文档将深入探讨这三大技术在...

    使用Hibernate开发租房系统78.

    查询房源则可以使用`Query`或`Criteria` API,通过HQL(Hibernate Query Language)或SQL编写查询语句。 进一步地,租房系统可能需要处理复杂的业务逻辑,比如租赁合同的签订和管理。这可能涉及到多个实体间的关联...

    Hibernate泛型Dao

    【描述】"基于hibernate5 泛型Dao实例,下载后改一下数据库配置直接可以用",意味着这个压缩包文件提供了一个已经实现好的Hibernate5版本的泛型Dao示例项目。用户只需要根据自己的数据库环境修改相应的配置信息,就...

Global site tag (gtag.js) - Google Analytics