[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