我不是在寻找Hibernate / JPA / JDBC实现,而是在寻求一种通用的设计模式。
谷歌搜索“分页”为我提供了大量信息,许多有趣的文章解释了如何在UI上实现分页以及各种或多或少都执行相同操作的实现。
简单的bean:
public class Person{ private String personName; private int age; // ... }
一个简单的DAO界面:
public interface PersonDAO{ Set<Person> getAllPersons(int start, int limit,String orderBy); Set<Person> findPersonsByName(String name, int start, int limit,String orderBy); }
和hibernate实现
@Repository public class PersonDAOImpl implements PersonDAO { @Autowired(required = true) private SessionFactory sessionFactory; public Set<Person> getAllPersons(int start, int limit, String orderBy){ Criteria crit = sessionFactory.getCurrentSession().createCriteria(Person.class); crit.setFirstResult(start); crit.setMaxResults(limit); crit.addOrder(Order.asc("personName")); return new LinkedHashSet<Person>(crit.list()); } public Set<Person> findPersonsByName(String name, int start, int limit, String orderBy){ Criteria crit = sessionFactory.getCurrentSession().createCriteria(Person.class); crit.add(Restrictions.eq("name", name)); crit.setFirstResult(start); crit.setMaxResults(limit); crit.addOrder(Order.asc(orderBy)); return new LinkedHashSet<Person>(crit.list()); }
现在,我在考虑是否必须在所有接口中都包含相似的参数,那么这里确实有问题。我可以将请求包装在请求bean对象中,然后将此bean传递给方法,就像这样
public class PersonRequest{ private int start; private int limit; private String orderBy; private String name; // ... }
然后
public interface PersonDAO{ Set<Person> getAllPersons(PersonRequest request); Set<Person> findPersonsByName(PersonRequest request); }
但是出于某种原因,这似乎也不自然。然后我在想Java中的varargs
public interface PersonDAO{ Set<Person> getAllPersons(Object... params); Set<Person> findPersonsByName(String name,Object... params); } @Repository public class PersonDAOImpl implements PersonDAO { @Autowired(required = true) private SessionFactory sessionFactory; public Set<Person> getAllPersons(Object... params){ Criteria crit = sessionFactory.getCurrentSession().createCriteria(Person.class); crit.setFirstResult((Integer)params[0]); crit.setMaxResults((Integer)params[1]); crit.addOrder(Order.asc("personName")); return new LinkedHashSet<Person>(crit.list()); } public Set<Person> findPersonsByName(String name, Object... params){ Criteria crit = sessionFactory.getCurrentSession().createCriteria(Person.class); crit.add(Restrictions.eq("name", name)); crit.setFirstResult((Integer)params[0]); crit.setMaxResults((Integer)params[1]); crit.addOrder(Order.asc((String)params[2])); return new LinkedHashSet<Person>(crit.list()); }
这似乎也有些脆弱,出于某种原因,我一直认为桥接模式可能会有所帮助,但仍然遥不可及。
知道您将如何处理吗?
如果您是我,我将不返回结果(Set)本身,而是返回封装结果检索的内容。某种ResultBuilder。看:
Set
public interface ResultBuilder<T> { ResultBuilder<T> withOffset(int offset); ResultBuilder<T> withLimit(int limit); ResultBuilder<T> orderedBy(String property); List<T> result(); }
然后更改DAO方法签名:
ResultBuilder<Person> findPersonsByName(String name);
这样,您就可以从查找族方法中排除与业务无关的参数。如果您不想让客户指定此参数,则不要让他指定。
只是要清楚:
public final class HibernateGenericResultBuilder<T> implements ResultBuilder<T> { private final Criteria criteria; public HibernateGenericResultBuilder(Criteria criteria) { this.criteria = criteria; } @Override public ResultBuilder<T> withOffset(int offset) { criteria.setFirstResult(offset); return this; } @Override public ResultBuilder<T> withLimit(int limit) { criteria.setMaxResults(limit); return this; } @Override public ResultBuilder<T> orderedBy(String property) { criteria.addOrder(Order.asc(property)); return this; } @Override public List<T> result() { return new LinkedHashSet<T>(criteria.list()); } }