通用搜索条件类型

时间:2012-08-02 04:45:38

标签: java

我的应用程序是使用表示层,服务层和数据访问层构建的。有多种服务和API通常需要从数据访问层检索一些数据。为了获得这样的数据,我经常需要将一些搜索条件从一个层传递到另一个层。例如,我可以传递from_date,to_date,email_id,user_id等属性。现在我试图传递一个对象,比如说SearchCriteria,而不是传递很多单独的参数。同样,不同的服务/ apis需要不同的SearchCriterias。

问题是,如何使其成为通用的,以使其可供所有服务使用。一种方法是拥有一个SearchCriteria对象,该对象将SEARCH_KEY的映射保存为value,其中SEARCH_KEY可以是枚举(具有FROM_DATE,TO_DATE等值)。根据SEARCH_KEY,我可以检索密钥并使用它。但这只适用于一层知道该地图所期望的值类型(整数,字符串)的情况。一层耦合到另一层,我认为这是不好的。我经历了这个问题 - Map with multiple value types with advantages of generics,它解决了类似的问题。这是一个很好的设计吗?还有更好的选择吗?

3 个答案:

答案 0 :(得分:2)

我刚刚使用新的标准API为Hibernate 5上的通用搜索做了这个解决方案。 我得到了一个类似于JavaIO的FileFilter的解决方案。

在GenericDAO,我实现了一般搜索方法:

public List<T> search(SearchFilter searchFilter) {
    CriteriaBuilder criteriaBuilder = getSession().getCriteriaBuilder();
    CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(getPersistentClass());
    Root<T> entityRoot = criteriaQuery.from(getPersistentClass());
    criteriaQuery.select(entityRoot);
    criteriaQuery.where(searchFilter.buildPredicate(criteriaBuilder, entityRoot));
    Query<T> query = getSession()
            .createQuery(criteriaQuery);
    return query.getResultList();
}

对于SearchFilter类(作为GenericDAO的嵌套类实现),一个非常简单的代码:

abstract class SearchFilter {
    abstract protected Predicate buildPredicate(CriteriaBuilder criteriaBuilder, Root<T> root);
}

现在使用它看起来像这样:

public List<Product> findByCategory(ProductCategory productCategory) {
    return search(new SearchFilter() {
        @Override
        protected Predicate buildPredicate(CriteriaBuilder criteriaBuilder, Root<Product> root) {
            return criteriaBuilder.equal(root.get("productCategory"), productCategory);
        }
    });
}

此解决方案允许通过更简单的实现减少特定DAO搜索的代码行数。

答案 1 :(得分:0)

你可以做这样的事情

编写枚举以保存参数键

enum ParameterKeys {

  SERIAL_NUMBER,
  SEARCH_KEY,
  FROM_DATE,
  ISVALID

}

编写一个包含参数值

的类
public class Parameter {

    private Object value;
    private Class<?> clazz;

    public Parameter(Object value) {
        setValue(value);
    }

    public void setValue(Object value) {
        this.value = value;
        this.clazz = value.getClass();
    }

    public Object getValue() {
        return clazz.cast(value);
    }

}

现在尝试制作参数Map

 public class Main {

        public static void main(String[] args) {
            Map<String,Parameter> _params = new HashMap<String, Parameter>();
            _params.put(ParameterKeys.SERIAL_NUMBER, new Parameter(1));
                 _params.put(ParameterKeys.SEARCH_KEY, new Parameter("query"));
            _params.put(ParameterKeys.FROM_DATE, new Parameter(new Date()));
            _params.put(ParameterKeys.ISVALID, new Parameter(1));
        System.out.println(_params.get(ParameterKeys.SERIAL_NUMBER).getValue().getClass().getCanonicalName());
    System.out.println(_params.get(ParameterKeys.SEARCH_KEY).getValue().getClass().getCanonicalName());     System.out.println(_params.get(ParameterKeys.FROM_DATE).getValue().getClass().getCanonicalName());    System.out.println(_params.get(ParameterKeys.FROM_DATE).getValue().getClass().getCanonicalName());

        }

    }

输出将是:

java.lang.Integer
java.lang.String
java.util.Date
java.lang.Boolean

您可以将此地图传递到不同的级别

答案 2 :(得分:0)

如果在运行时处理就足够了,你可以试试这个

public enum ParameterKeys {

  SERIAL_NUMBER {
      public Class<?> getType() {
          return Integer.class;
      }
  },
  SEARCH_KEY{
      public Class<?> getType() {
          return String.class;
      }
  },
  FROM_DATE{
      public Class<?> getType() {
          return Date.class;
      }
  },
  ISVALID{
      public Class<?> getType() {
          return Boolean.class;
      }
  };

public abstract Class<?> getType();

}

public class Parameter {

private Object value;
private Class<?> clazz;
private ParameterKeys key;

public Parameter(Object value,ParameterKeys key) throws Exception {
    this.key = key;
    setValue(value);
}

public void setValue(Object value) throws Exception{
    this.value = value;
    this.clazz = value.getClass();
    if(!clazz.getCanonicalName().equals(key.getType().getCanonicalName())) {
        throw new Exception("Type Mismatch between Parameter Key : " + key + " and Value : " + value);
    }
}

public Object getValue() {
    return clazz.cast(value);
}

}

public class Main {

public static void main(String[] args) {
    Map<ParameterKeys,Parameter> _params = new HashMap<ParameterKeys, Parameter>();
    try {
    _params.put(ParameterKeys.SERIAL_NUMBER, new Parameter(1,ParameterKeys.SERIAL_NUMBER));
    _params.put(ParameterKeys.SEARCH_KEY, new Parameter("query",ParameterKeys.SEARCH_KEY));
    _params.put(ParameterKeys.FROM_DATE, new Parameter(new Date(),ParameterKeys.FROM_DATE));
    _params.put(ParameterKeys.FROM_DATE, new Parameter(true,ParameterKeys.FROM_DATE));
    } catch(Exception e) {
        System.out.println(e.getMessage());
    }

}

}

这将打印出以下异常

参数键类型不匹配:FROM_DATE和值:true