[SPRING] 일반적인 페이지 매김을 구현하는 방법
SPRING일반적인 페이지 매김을 구현하는 방법
나는 Hibernate / JPA / JDBC 구현을 찾고 있지는 않지만 일반적인 디자인 패턴을 찾고있다.
"페이지 매김"을 검색하면 많은 정보와 UI에서 페이지 매김을 구현하는 방법 및 다소 차이가있는 다양한 구현을 설명하는 많은 흥미로운 기사를 얻을 수 있습니다.
Spring 3.0.5를 사용하고 있기 때문에 Spring MVC 3에서 페이지 매김을 구현하는 좋은 참고 자료를 발견했다.
간단한 콩 :
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);
}
그리고 최대 절전 모드 구현
@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());
}
이제 모든 인터페이스에 비슷한 매개 변수를 포함해야한다면 정말 잘못된 것이 있습니다. 요청 빈 객체에 요청을 래핑하고이 빈을 메소드에 전달할 수 있습니다.
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());
}
이것 역시 너무 가벼운 것처럼 보이기 때문에, 나는 다리 패턴이 도움이 될 수 있다고 생각하고 있지만 여전히 부적절하다.
이 문제를 어떻게 처리 할 생각인가요?
해결법
-
==============================
1.내가 너라면 나는 결과 (Set) 자체가 아니라 결과 검색을 캡슐화하는 것을 반환 할 것이다. ResultBuilder의 일종입니다. 보기:
내가 너라면 나는 결과 (Set) 자체가 아니라 결과 검색을 캡슐화하는 것을 반환 할 것이다. ResultBuilder의 일종입니다. 보기:
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()); } }
-
==============================
2.여기에 전략 패턴을 적용하는 것이 좋습니다.
여기에 전략 패턴을 적용하는 것이 좋습니다.
기본적으로 매개 변수로 시작 및 제한을 제공하거나 varargs에 래핑하는 대신 실제 개체를 만들어서 거기에 넣고 기준에 따라 페이징 설정의 책임을이 개체로 옮깁니다.
대략 말하기 (나는 컴파일하지 않는다 ...) :
public interface PagingSpecification { void apply(Criteria criteria); } public class ConcretePagingSpecification implements PagingSpecification { private int start; private int limit; public ConcretePagingSpecification(int start, int limit) { this.start = start; this.limit = limit; } public void apply(Criteria crit) { crit.setFirstResult(start); crit.setMaxResults(limit); } }
그리고 이것을 물론 당신의 파인더에 넘겨주고 명백한 장소에서 호출하십시오.
이 기능의 한 가지 장점은 아무것도 수행하지 않는 NullPagingSpecification 구현을 만들 수 있으므로 페이징을 실제로 원하지 않을 때 동일한 코드를 사용할 수 있다는 것입니다.
또 하나는 PagingSpecification 클래스에 (실제 페이징을 허용하기 위해) 필요할 가능성이있는 next () 및 previous () 메소드를 이동하고 더 많은 코드를 공유 할 수 있다는 것입니다.
from https://stackoverflow.com/questions/5412059/how-to-implement-general-pagination by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring MVC 3.2 Thymeleaf Ajax 파편들 (0) | 2019.03.01 |
---|---|
[SPRING] 상태없는 서버는 어떻게 작동합니까? (0) | 2019.03.01 |
[SPRING] Spring의 OpenEntityManagerInViewFilter를 사용하지 않는 이유 (0) | 2019.03.01 |
[SPRING] Hibernate / Spring : 지연 초기화에 실패 - 세션이나 세션이 닫히지 않았습니다. (0) | 2019.03.01 |
[SPRING] 많은 관계를 설정하거나 목록을 최대 절전 모드로 전환 하시겠습니까? (0) | 2019.03.01 |