问题描述
我不是在寻找一个Hibernate / JPA / JDBC实现,而是一般的设计模式。
Googling分页给了我大量的信息,很多有趣的文章解释了如何在UI上实现分页,或多或少地执行相同的各种实现。 / p>
由于我使用的是Spring 3.0.5,我偶然发现了这个很好的参考文章。
简单bean:
public class Person {
private String personName;
private int age;
// ...
}
一个简单的DAO界面: p>
public interface PersonDAO {
Set< Person> getAllPersons(int start,int limit,String orderBy);
设置< Person> findPersonsByName(String name,int start,int limit,String orderBy);
}
和hibernate实现
@Repository
public class PersonDAOImpl实现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));
返回新的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));
返回新的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请求);
设置< Person> findPersonsByName(PersonRequest request);
}
但由于某种原因,这似乎也不自然。然后我想到Java中的varargs
public interface PersonDAO {
Set< Person> getAllPersons(Object ... params);
设置< Person> findPersonsByName(String name,Object ... params);
}
@Repository
public class PersonDAOImpl实现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));
返回新的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]));
返回新的LinkedHashSet< Person>(crit.list());
}
这似乎有点脆弱,由于某种原因我一直认为桥梁模式可能是有帮助但仍然是遥远的不适。
任何想法如何处理这个?
如果我是你,我不会返回结果( Set
)本身,而是封装检索结果的东西。某种ResultBuilder。看看:
public interface ResultBuilder< T> {
ResultBuilder< T> withOffset(int offset);
ResultBuilder< T> withLimit(int limit);
ResultBuilder< T> orderedBy(String属性);
列表< T>结果();
}
然后更改DAO方法签名:
ResultBuilder< Person> findPersonsByName(String name);
这样,您可以从find-family方法中考虑出与业务无关的参数。
如果你不想让客户指定这个参数,那么不要让他。
只是为了清楚:
public final class HibernateGenericResultBuilder< T>实现ResultBuilder< T> {
私人最终标准条件;
public HibernateGenericResultBuilder(Criteria criteria){
this.criteria = criteria;
}
@Override public ResultBuilder< T> withOffset(int offset){
criteria.setFirstResult(offset);
返回这个;
}
@Override public ResultBuilder< T> withLimit(int limit){
criteria.setMaxResults(limit);
返回这个;
}
@Override public ResultBuilder< T> orderedBy(String property){
criteria.addOrder(Order.asc(property));
返回这个;
}
@Override public List< T> result(){
return new LinkedHashSet< T>(criteria.list());
}
}
I am not looking for a Hibernate/JPA/JDBC implementation, but for a general design pattern.
Googling "pagination" gives me loads of information, lot of interesting articles that explain how to implement pagination on the UI and various implementations which more or less do the same.
Since I am using Spring 3.0.5, and I stumbled this good reference article How to implement pagination in Spring MVC 3.
Simple bean:
public class Person{
private String personName;
private int age;
// ...
}
A simple DAO interface:
public interface PersonDAO{
Set<Person> getAllPersons(int start, int limit,String orderBy);
Set<Person> findPersonsByName(String name, int start, int limit,String orderBy);
}
And the hibernate implementation
@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());
}
Now, I am thinking if I have to include similar parameters across all the interface then there is something really wrong here. Either I can wrap the request in a request bean object and pass this bean to the methods, something like this
public class PersonRequest{
private int start;
private int limit;
private String orderBy;
private String name;
// ...
}
And subsequently
public interface PersonDAO{
Set<Person> getAllPersons(PersonRequest request);
Set<Person> findPersonsByName(PersonRequest request);
}
But this too seems unnatural, for some reason. Then I am thinking of varargs in Java
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());
}
This too seems bit flimsy, for some reason I keep thinking bridge pattern could be helpful but still is distant unfit.
Any idea how you would deal with this?
If I were you I would return not the result (Set
) itself but something that encapsulates retrieval of the result. Some sort of ResultBuilder. Look:
public interface ResultBuilder<T> {
ResultBuilder<T> withOffset(int offset);
ResultBuilder<T> withLimit(int limit);
ResultBuilder<T> orderedBy(String property);
List<T> result();
}
and then change DAO method signature:
ResultBuilder<Person> findPersonsByName(String name);
This way you can factor out business-irrelevant arguments from find-family methods.If you don't want to make client specify this params then don't make him.
Just to be clear:
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());
}
}
这篇关于如何实现一般分页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!