我的应用程序是使用表示层,服务层和数据访问层构建的。有多种服务和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,它解决了类似的问题。这是一个很好的设计吗?还有更好的选择吗?
答案 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