sac*_*ink 19 java spring pagination design-patterns hibernate
我不是在寻找Hibernate/JPA/JDBC实现,而是寻找一般的设计模式.
谷歌搜索"分页"给了我大量的信息,许多有趣的文章,解释如何在UI上实现分页和各种实现,或多或少相同.
由于我使用的是Spring 3.0.5,我偶然发现了这篇很好的参考文章如何在Spring MVC 3中实现分页.
简单的豆子:
public class Person{
private String personName;
private int age;
// ...
}
Run Code Online (Sandbox Code Playgroud)
一个简单的DAO接口:
public interface PersonDAO{
Set<Person> getAllPersons(int start, int limit,String orderBy);
Set<Person> findPersonsByName(String name, int start, int limit,String orderBy);
}
Run Code Online (Sandbox Code Playgroud)
和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());
}
Run Code Online (Sandbox Code Playgroud)
现在,我在想如果我必须在所有界面中包含类似的参数,那么这里确实存在一些问题.要么我可以将请求包装在请求bean对象中,并将此bean传递给方法,就像这样
public class PersonRequest{
private int start;
private int limit;
private String orderBy;
private String name;
// ...
}
Run Code Online (Sandbox Code Playgroud)
随后
public interface PersonDAO{
Set<Person> getAllPersons(PersonRequest request);
Set<Person> findPersonsByName(PersonRequest request);
}
Run Code Online (Sandbox Code Playgroud)
但出于某种原因,这似乎也不自然.然后我在想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());
}
Run Code Online (Sandbox Code Playgroud)
这似乎有点脆弱,出于某种原因我一直认为桥模式可能会有所帮助,但仍然是遥不合适.
你知道怎么处理这个吗?
小智 24
如果我是你,我将返回结果(Set)本身,而不是封装结果检索的东西.某种ResultBuilder.看:
public interface ResultBuilder<T> {
ResultBuilder<T> withOffset(int offset);
ResultBuilder<T> withLimit(int limit);
ResultBuilder<T> orderedBy(String property);
List<T> result();
}
Run Code Online (Sandbox Code Playgroud)
然后更改DAO方法签名:
ResultBuilder<Person> findPersonsByName(String name);
Run Code Online (Sandbox Code Playgroud)
这样,您可以从find-family方法中分解出与业务无关的参数.如果你不想让客户指定这个参数,那么不要让他.
只是要清楚:
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());
}
}
Run Code Online (Sandbox Code Playgroud)