public List getPersonList(int max, int whichpage) {
try {
int index = (whichpage - 1) * max;
Query query = em.createQuery("from Person p order by personid asc");
List list = query.setMaxResults(max).setFirstResult(index).getResultList();
em.clear();// 分离内存中受EntityManager管理的实体bean,让VM进行垃圾回收
return list;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
上面是网上查到JPA分页的例子,发现JPA分页有2个缺陷
1. 类似于上例,用query.setFirstResult(5);query.setMaxResults(2)是想找第5--7条
虽然结果正确,但看了log中的sql,竟然是select top 7 然后返回第6,7两条。而我们自己写sql则是可通过一定的写法直接返回第6.7条。 如果数据量大JPA且不是要查询装载很多额外的数据?
2. 用该方法查找出来的无法缓存?请问是这样吗,有没有更好的办法?
如例子中如果不用em.clear会有什么副作用?
解决方案 »
- Intellij 11.0编写servlet的问题,提示无法解析servlet
- struts2如何实现这样的需求
- 请问一下谁用过dhcp4java框架开发过dhcp服务器,100分
- spring MVC出错的问题
- struts 的ActionErrors的classcastException问题
- 求救:关于jdbc 存取 oracle clob 的问题?
- 在J2EE平台下开发一个典型应用 http:/127.0.0.1:8000/ch1/wer.jsp 找不到8000服务器
- jdbc事务问题 数据库sqlserver
- 有没有做过LDAP研究的朋友,留个email或qq号交个朋友交流一下行吗?十分感激
- jacob excel转PDF报错
- 初学EJB2,关于jboss部署local问题,老报找不到jndi,详细请看下面
- 如何将war 转成项目?
如果数据库支持了,但jpa的实现没使用拼装更好的sql,那是jpa的实现做的不够好。
你就单凭这样测试,就说jpa的分页效率底下?你是跟什么比?
100万比数据,你同时用jpa和hibernate,ibatis试试看
而不是像JPA那样先找出7个实体,然后在返回后面的2个,这里就多余了5个实体的装载。
我说的效率低,是指多抓了数据,占时间,占内存
if ( offset > 0 ) {
throw new UnsupportedOperationException( "query result offset is not supported" );
}
return new StringBuffer( querySelect.length() + 8 )
.append( querySelect )
.insert( getAfterSelectInsertPoint( querySelect ), " top " + limit )
.toString();
}可以看到使用的是top N的方式。
让我们再来看看新的hibernate4.1.2中的dialect,发现多了2个sqlserverdialect:SQLServer2005Dialect,SQLServer2008Dialect。说明hibernate4针对sqlserver2005,2008做了增强。 /**
* Add a LIMIT clause to the given SQL SELECT (HHH-2655: ROW_NUMBER for Paging)
*
* The LIMIT SQL will look like:
*
* <pre>
* WITH query AS (
* SELECT ROW_NUMBER() OVER (ORDER BY orderby) as __hibernate_row_nr__,
* original_query_without_orderby
* )
* SELECT * FROM query WHERE __hibernate_row_nr__ BEETWIN offset AND offset + last
* </pre>
*
* @param querySqlString The SQL statement to base the limit query off of.
* @param hasOffset Is the query requesting an offset?
*
* @return A new SQL statement with the LIMIT clause applied.
*/
@Override
public String getLimitString(String querySqlString, boolean hasOffset) {
StringBuilder sb = new StringBuilder( querySqlString.trim().toLowerCase() ); int orderByIndex = sb.indexOf( "order by" );
CharSequence orderby = orderByIndex > 0 ? sb.subSequence( orderByIndex, sb.length() )
: "ORDER BY CURRENT_TIMESTAMP"; // Delete the order by clause at the end of the query
if ( orderByIndex > 0 ) {
sb.delete( orderByIndex, orderByIndex + orderby.length() );
} // HHH-5715 bug fix
replaceDistinctWithGroupBy( sb ); insertRowNumberFunction( sb, orderby ); // Wrap the query within a with statement:
sb.insert( 0, "WITH query AS (" ).append( ") SELECT * FROM query " );
sb.append( "WHERE __hibernate_row_nr__ >= ? AND __hibernate_row_nr__ < ?" ); return sb.toString();
}看到注释中有说明,使用了新的方式来做分页查询。所以,正如我上面所说的,数据库支持的时候,但jpa的实现可能没有做好。如果楼主用的hibernate4,就可以通过配置使用针对更新数据库的dialect:SQLServer2005Dialect或SQLServer2008Dialect