如何实现一般分页

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)