没有分页的时候,我们的处理可能是这样的:
public List<Order> QueryDateForUser(User user, Date deliverydate)
{
}
此时返回的只是结果集;通过结果集当然可以知道返回的个数
没有分页的时候,我们的处理可能是这样的:
// pageNo - 指定页
// pageSize - 每页大小
public Page<Order> QueryDateForUser_Page(User user, Date deliverydate, int pageNo, int pageSize)
{
}
此时返回的是指定页的信息Page。Page中应该包括当前页结果集List<Order>;还包括分页情况:总条数;以及之前的分页参数:当前页数和每页条数。
有和没有分页的时候,我们希望统一处理。可能的解决方法是这样的:
public List<Order> QueryDateForUser(User user, Date deliverydate, Page page)
{
}
page信息由使用者传递过去。
- 输入参数时,page中应该先确定分页参数:每页条数,当前页;
- 输出参数时,page中应该包含记录总数;有了记录总数,可以知道可以分多少页等其它分页信息
- 返回值表示当前页内的结果集
这样,避免前面两种返回值不同的情况。约定返回值相同,可以让用户在进行分页与否切换时,改动较小。而从实现角度来看,从没有分页到有分页的切换,实际上就是在原来的代码中,插入一个分页处理。插入的逻辑如下面部分:
public List<Order> QueryDateForUser(User user, Date deliverydate, Page page)
{
List<Order> rtn = null;
Query q = CreateNameQuery("QueryDateForUser")
.setParameter(1, user)
.setParameter(2, deliverydate);
//-设置分页信息-
if(null!=page)
{
long totalCount = getCountFromNameQuery("QueryDateForUser", user, deliverydate);
page.setTotalCount(totalCount);
SetQueryPage(q, page);
}
rtn = (List<Order>) q.getResultList();
return rtn;
}
分页处理,在JPA中其实很简单,仅仅是设置页的起始值setFirstResult(注意从0开始);以及页的记录条数setMaxResults(注意:如果从起始值到最后条数小于页条数,会自动截短)
Query SetQueryPage(Query query, Page page)
{
if(null!=page)
{
query.setFirstResult(page.getPageNo()*page.getPageSize());
query.setMaxResults(page.getPageSize());
}
return query;
}
全部问题都落在总条数这个问题上了。
简单的方法是,两个JPQL。一定有一个Select * 的JPQL,作为结果集返回。另一个再写一个Select count(*),表示个数而已嘛!
这种方法唯一的麻烦就是一些语句要写两遍。如下:
@Entity
@Table(name = "orders")
@NamedQueries ({
@NamedQuery (name= "QueryForUser" , query= "FROM Order WHERE user=?1 ORDER BY deliverydate DESC" ),
@NamedQuery (name= "QueryDateForUser" , query= "FROM Order WHERE user=?1 AND deliverydate =?2 ORDER BY deliverydate DESC"),
@NamedQuery (name= "QueryOrderNoForUser" , query= "FROM Order WHERE user=?1 AND orderNo LIKE CONCAT('%',?2,'%') ORDER BY deliverydate DESC"),
@NamedQuery (name= "QueryDateOrderNoForUser" , query= "FROM Order WHERE user=?1 AND deliverydate =?2 AND orderNo LIKE CONCAT('%',?3,'%') ORDER BY deliverydate DESC"),
@NamedQuery (name= "GetRecentOrder" , query= "FROM Order WHERE user=?1 AND deliverydate between ?2 AND ?3 ORDER BY deliverydate")
})
public class Order implements Serializable
{}
如何省点配置,自动获取NamedQuery对应的query呢。
最开始的方法总是想从JPA的方法入手。后来发现还是回归原始,直接从入手。如下:
String GetJpqlFromNamedQuery(Class<T> _entityClass, String queryname)
{
String query = "";
Annotation an[] = _entityClass.getAnnotations();
for(int i=0;i<an.length; i++)
{
if(an[i].annotationType()==NamedQueries.class)
{
NamedQueries ns = (NamedQueries)an[i];
for(NamedQuery n : ns.value())
{
if(n.name().equals(queryname))
query = n.query();
}
break;
}
else if(an[i].annotationType()==NamedQuery.class)
{
NamedQuery n = (NamedQuery)an[i];
if(n.name().equals(queryname))
query = n.query();
break;
}
}
return query;
}
至于有了query,拼凑SELECT COUNT 就很简单了。
只要知道每页个数,当前页,总记录数。构造类似分页就很简单了。分页包括:总条数,当前记录数,首页尾页,上一页,下一页,页码,跳转!
评论