[jboss-user] [JBoss Seam] - Share my implementation of EntityQuery by Entity Example, an

zjsun do-not-reply at jboss.com
Wed Jan 16 22:12:51 EST 2008


Structure:
    EntityQuery
        ExampleEntityQuery     +  EntityQueryState
            RestrictedExampleEntityQuery
Note:
    ExampleEntityQuery used to generate dynamic ejbql at runtime according to the entity class and entity instance ...
    EntityQueryState used to hold query state, include orderby info, page info, example entity...
    RestrictedExampleEntityQuery used to control user permission on this query, by adding more restriction "where" ejbql


  | public abstract class ExampleEntityQuery<E> extends EntityQuery {
  | 
  | 	private static final long serialVersionUID = 4830838552107053677L;
  | 
  | 	public static final Pattern FROM_PATTERN = Pattern.compile(
  | 			"(^|\\s)(from)\\s", Pattern.CASE_INSENSITIVE);
  | 
  | 	public static final Pattern ORDER_CLAUSE_PATTERN = Pattern
  | 			.compile("^[\\w\\.,\\s]*$");
  | 
  | 	public static final Pattern ORDER_PATTERN = Pattern.compile(
  | 			"\\s(order)(\\s)+by\\s", Pattern.CASE_INSENSITIVE);
  | 
  | 	public static final Pattern WHERE_PATTERN = Pattern.compile(
  | 			"\\s(where)\\s", Pattern.CASE_INSENSITIVE);
  | 
  | 	@Logger
  | 	private Log log;
  | 
  | 	// private EntityQueryState<E> state;
  | 	public abstract void setState(EntityQueryState<E> state);
  | 
  | 	public abstract EntityQueryState<E> getState();
  | 
  | 	protected String buildCountEjbql() {
  | 		// return super.getCountEjbql();
  | 		String ejbql = getRenderedEjbql();
  | 		boolean distincted = ejbql.startsWith("select distinct");
  | 
  | 		Matcher fromMatcher = FROM_PATTERN.matcher(ejbql);
  | 		if (!fromMatcher.find()) {
  | 			throw new IllegalArgumentException("no from clause found in query");
  | 		}
  | 		int fromLoc = fromMatcher.start(2);
  | 
  | 		Matcher orderMatcher = ORDER_PATTERN.matcher(ejbql);
  | 		int orderLoc = orderMatcher.find() ? orderMatcher.start(1) : ejbql
  | 				.length();
  | 
  | 		String countQl = "select count(*) ";
  | 		if (distincted) {
  | 			Class entityClass = ReflectionsUtils.getClassParameterType(
  | 					getClass(), 0);
  | 			// String entityClassName = entityClass.getSimpleName();
  | 			String entityAliasName = EntityUtils
  | 					.getEntityAliasName(entityClass);
  | 			countQl = "select count(distinct " + entityAliasName + ") ";
  | 		}
  | 		countQl += ejbql.substring(fromLoc, orderLoc);
  | 
  | 		logQl("Seam ext (Query countEjbql) : " + countQl);
  | 		return countQl;
  | 	}
  | 
  | 	protected String buildEjbql() {
  | 		Class entityClass = ReflectionsUtils.getClassParameterType(getClass(),
  | 				0);
  | 		String entityClassName = entityClass.getSimpleName();
  | 		String entityAliasName = EntityUtils.getEntityAliasName(entityClass);
  | 
  | 		StringBuffer joinBuilder = new StringBuffer();
  | 		StringBuffer whereBuilder = new StringBuffer();
  | 		boolean joined = false;
  | 
  | 		if (getState() != null) {
  | 			if (getState().getExample() != null) {
  | 				for (PropertyDescriptor pd : PropertyUtils
  | 						.getPropertyDescriptors(entityClass)) {
  | 					if (ReflectionsUtils.isInstanceOf(pd.getPropertyType(),
  | 							Collection.class.getName())) {
  | 
  | 						Field field = ReflectionsUtils.getField(entityClass, pd
  | 								.getName());
  | 						Method fieldGetterMethod = ReflectionsUtils
  | 								.getGetterMethod(entityClass, pd.getName());
  | 						Collection fieldValue = null;
  | 						try {
  | 							fieldValue = (Collection) fieldGetterMethod.invoke(
  | 									getState().getExample(), new Object[] {});
  | 						} catch (Exception e) {
  | 							e.printStackTrace();
  | 						}
  | 
  | 						if (fieldValue != null && fieldValue.size() > 0) {
  | 							Class propertyEntityClass = ReflectionsUtils
  | 									.getCollectionElementType(field
  | 											.getGenericType());
  | 							String propertyAliasName = EntityUtils
  | 									.getEntityAliasName(propertyEntityClass);
  | 							joinBuilder.append(" left join " + entityAliasName
  | 									+ "." + pd.getName() + " "
  | 									+ propertyAliasName);
  | 
  | 							joined = true;
  | 						}
  | 					}
  | 				}
  | 			}
  | 
  | 			// 如果是针对当前entity的一个property说对应的entity进行查询
  | 			if (getState().getQueryPropertyName() != null) {
  | 				Field field = ReflectionsUtils.getField(entityClass, getState()
  | 						.getQueryPropertyName());
  | 				boolean bCollectionType = ReflectionsUtils.isInstanceOf(field
  | 						.getType(), Collection.class.getName());
  | 
  | 				Class propertyEntityClass = field.getType();
  | 				if (bCollectionType) {
  | 					propertyEntityClass = ReflectionsUtils
  | 							.getCollectionElementType(field.getGenericType());
  | 				}
  | 
  | 				String propertyAliasName = EntityUtils
  | 						.getEntityAliasName(propertyEntityClass);
  | 
  | 				String joinItem = " join " + entityAliasName + "."
  | 						+ field.getName() + " " + propertyAliasName;
  | 
  | 				// TODO:暂时使用粗糙的检测是否存在
  | 				if (joinBuilder.toString().indexOf(joinItem) == -1) {
  | 					if (bCollectionType) {
  | 						joinBuilder.append(" left").append(joinItem);
  | 					} else {
  | 						joinBuilder.append(joinItem);
  | 					}
  | 					whereBuilder.append(propertyAliasName + " is not null");
  | 					joined = true;
  | 				}
  | 			}
  | 		}
  | 
  | 		StringBuffer selectBuilder = new StringBuffer();
  | 		if (joined) {
  | 			selectBuilder.append("select distinct ");
  | 		} else {
  | 			selectBuilder.append("select ");
  | 		}
  | 
  | 		if (getState() != null && getState().getQueryPropertyName() != null) {
  | 			Field field = ReflectionsUtils.getField(entityClass, getState()
  | 					.getQueryPropertyName());
  | 			boolean bCollectionType = ReflectionsUtils.isInstanceOf(field
  | 					.getType(), Collection.class.getName());
  | 
  | 			Class propertyEntityClass = field.getType();
  | 			if (bCollectionType) {
  | 				propertyEntityClass = ReflectionsUtils
  | 						.getCollectionElementType(field.getGenericType());
  | 			}
  | 
  | 			String propertyAliasName = EntityUtils
  | 					.getEntityAliasName(propertyEntityClass);
  | 			selectBuilder.append(propertyAliasName);
  | 		} else {
  | 			selectBuilder.append(entityAliasName);
  | 		}
  | 
  | 		selectBuilder.append(" from ").append(entityClassName).append(" ")
  | 				.append(entityAliasName).append(joinBuilder);
  | 		if (whereBuilder.length() > 0) {
  | 			selectBuilder.append(" where ").append(whereBuilder);
  | 		}
  | 
  | 		logQl("Seam ext (Query ejbql) : " + selectBuilder.toString());
  | 		return selectBuilder.toString();
  | 	}
  | 
  | 	protected List<QueryJoin> buildJoins() {
  | 		List<QueryJoin> joins = new ArrayList<QueryJoin>();
  | 		return joins;
  | 	}
  | 
  | 	protected List<String> buildRestrictions() {
  | 		List<String> restrictions = new ArrayList<String>();
  | 		if (getState() != null && getState().getExample() != null) {
  | 			Class entityClass = ReflectionsUtils.getClassParameterType(
  | 					getClass(), 0);
  | 			// String entityClassName = entityClass.getSimpleName();
  | 			String entityAliasName = EntityUtils
  | 					.getEntityAliasName(entityClass);
  | 			String queryComponentName = Seam.getComponentName(getClass());
  | 
  | 			for (PropertyDescriptor pd : PropertyUtils
  | 					.getPropertyDescriptors(entityClass)) {
  | 				if (!ReflectionsUtils.isInstanceOf(pd.getPropertyType(),
  | 						Class.class.getName())) {
  | 					if (ReflectionsUtils.isInstanceOf(pd.getPropertyType(),
  | 							String.class.getName())) {
  | 						// 如果String类型,则使用 like 查询
  | 						restrictions.add("lower(" + entityAliasName + "."
  | 								+ pd.getName() + ") like " + "lower('%'||#{"
  | 								+ queryComponentName + ".state.example."
  | 								+ pd.getName() + "}||'%')");
  | 					} else if (ReflectionsUtils.isInstanceOf(pd
  | 							.getPropertyType(), Collection.class.getName())) {
  | 						// 如果是Collection,则é
åˆå‰é¢çš„left join 使用in子查询方式
  | 						Field field = ReflectionsUtils.getField(entityClass, pd
  | 								.getName());
  | 
  | 						Method fieldGetterMethod = ReflectionsUtils
  | 								.getGetterMethod(entityClass, pd.getName());
  | 						Collection fieldValue = null;
  | 						try {
  | 							fieldValue = (Collection) fieldGetterMethod.invoke(
  | 									getState().getExample(), new Object[] {});
  | 						} catch (Exception e) {
  | 							e.printStackTrace();
  | 						}
  | 
  | 						if (fieldValue != null && fieldValue.size() > 0) {
  | 							Class propertyEntityClass = ReflectionsUtils
  | 									.getCollectionElementType(field
  | 											.getGenericType());
  | 							String propertyAliasName = EntityUtils
  | 									.getEntityAliasName(propertyEntityClass);
  | 
  | 							restrictions.add(propertyAliasName + " in (select "
  | 									+ propertyAliasName + "_ from "
  | 									+ propertyEntityClass.getSimpleName() + " "
  | 									+ propertyAliasName + "_ where "
  | 									+ propertyAliasName + "_ in (#{"
  | 									+ queryComponentName + ".state.example."
  | 									+ pd.getName() + "}))");
  | 						}
  | 					} else {
  | 						// å
¶ä½™ç›´æŽ¥è¿›è¡Œ = 查询
  | 						restrictions.add(entityAliasName + "." + pd.getName()
  | 								+ " = " + "#{" + queryComponentName
  | 								+ ".state.example." + pd.getName() + "}");
  | 					}
  | 				}
  | 			}
  | 		}
  | 
  | 		return restrictions;
  | 	}
  | 
  | 	@Override
  | 	public void validate() {
  | 		super.validate();
  | 		if (getState() == null) {
  | 			// throw new IllegalStateException("state is null");
  | 		}
  | 	}
  | 
  | 	@Override
  | 	protected String getRenderedEjbql() {
  | 		String ql = super.getRenderedEjbql();
  | 		logQl("Seam ext (Query renderedEjbql) : " + ql);
  | 		return ql;
  | 	}
  | 
  | 	@Override
  | 	protected String getCountEjbql() {
  | 		return buildCountEjbql();
  | 	}
  | 
  | 	@Override
  | 	public Integer getFirstResult() {
  | 		return getState() == null ? super.getFirstResult() : getState()
  | 				.getCurrentPage();
  | 	}
  | 
  | 	@Override
  | 	public Integer getMaxResults() {
  | 		return getState() == null ? super.getMaxResults() : getState()
  | 				.getPageSize();
  | 	}
  | 
  | 	@Override
  | 	public String getOrder() {
  | 		return getState() == null ? super.getOrder() : getState().getOrderBy();
  | 	}
  | 
  | 	@Override
  | 	protected boolean isRestrictionParameterSet(Object parameterValue) {
  | 		boolean bSet = super.isRestrictionParameterSet(parameterValue);
  | 		if (bSet) {
  | 			if (parameterValue != null && parameterValue instanceof Collection) {
  | 				bSet = ((Collection) parameterValue).size() > 0;
  | 			}
  | 		}
  | 		return bSet;
  | 	}
  | 
  | 	@Override
  | 	public String getEjbql() {
  | 		return buildEjbql();
  | 	}
  | 
  | 	@Override
  | 	public List<String> getRestrictions() {
  | 		return buildRestrictions();
  | 	}
  | 
  | 	public void refreshQuery() {
  | 		// clear the parsed QL
  | 		setEjbql(null);
  | 		setRestrictions(null);
  | 		super.refresh();
  | 	}
  | 
  | 	private void logQl(String ql) {
  | 		log.info(ql);
  | 	}
  | 
  | }
  | 
  | 


  | public class EntityQueryState<E> implements Serializable {
  | 
  | 	private static final long serialVersionUID = 4999435737345385599L;
  | 
  | 	private E example;
  | 
  | 	private Integer pageSize;
  | 
  | 	private Integer currentPage;
  | 
  | 	private String orderBy;
  | 
  | 	// 用于标识是否查询当前Entity的某个property(Entity类型)的List
  | 	private String queryPropertyName;
  | 	
  | 	// TODO:how to implement?
  | 	private List<QueryJoin> queryJoins = new ArrayList<QueryJoin>();
  | 
  | 	public E getExample() {
  | 		return example;
  | 	}
  | 
  | 	public void setExample(E entity) {
  | 		this.example = entity;
  | 	}
  | 
  | 	public String getOrderBy() {
  | 		return orderBy;
  | 	}
  | 
  | 	public void setOrderBy(String orderby) {
  | 		this.orderBy = orderby;
  | 	}
  | 
  | 	public Integer getPageSize() {
  | 		return pageSize;
  | 	}
  | 
  | 	public void setPageSize(Integer pageSize) {
  | 		this.pageSize = pageSize;
  | 	}
  | 
  | 	public Integer getCurrentPage() {
  | 		return currentPage;
  | 	}
  | 
  | 	public void setCurrentPage(Integer currentPage) {
  | 		this.currentPage = currentPage;
  | 	}
  | 
  | 	public String getQueryPropertyName() {
  | 		return queryPropertyName;
  | 	}
  | 
  | 	public void setQueryPropertyName(String propertyName) {
  | 		this.queryPropertyName = propertyName;
  | 	}
  | 
  | 	public List<QueryJoin> getQueryJoins() {
  | 		return queryJoins;
  | 	}
  | 
  | 	public void setQueryJoins(List<QueryJoin> queryJoins) {
  | 		this.queryJoins = queryJoins;
  | 	}
  | }
  | 
  | 



  | public abstract class RestrictedExampleEntityQuery<E> extends
  | 		ExampleEntityQuery<E> {
  | 
  | 	private static final long serialVersionUID = -5768415674705835414L;
  | 
  | 	@Override
  | 	protected String buildEjbql() {
  | 		/**
  | 		 * 由于restriction方式里面只能使用固定结构的、且只支持一个参数的、且之间是andå
³ç³»çš„ QL
  | 		 * 受此限制,暂且将行实例条件表达式作为主QL的一部分
  | 		 */
  | 		StringBuffer builder = new StringBuffer().append(super.buildEjbql());
  | 		if (WHERE_PATTERN.matcher(builder).find()) {
  | 			builder.append(" and ");
  | 		} else {
  | 			builder.append(" where ");
  | 		}
  | 		builder.append(getRestrictedQl());
  | 		return builder.toString();
  | 	}
  | 
  | 	protected String getRestrictedQl() {
  | 		return EntityQuerySecurityRestriction.getRestrictionQl(ReflectionsUtils
  | 				.getClassParameterType(getClass(), 0));
  | 	}
  | }
  | 
  | 

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4120699#4120699

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4120699




More information about the jboss-user mailing list