版本hibernate3.2.6
数据库sql server 2k
hibernate左外连接同时即时抓取集合并利用setMaxResults()和setFirstResult()进行分页会出现
WARN [main] QueryTranslatorImpl.list(328) | firstResult/maxResults specified with collection fetch; applying in memory!的警告
在hibernate实战一书中也提到这样的语句在语义上就是错的,并且hibernate会退回到在内存中现在结果
Query execution options that are based on the SQL result rows, such as pag-ination with setMaxResults()/setFirstResult(), are semantically incor-rect if a collection is eagerly fetched. If you have an eager fetched collectionin your query, at the time of writing, Hibernate falls back to limiting theresult in-memory, instead of using SQL.
举个例子:
Group和User是1:n
方式一:
String hql = new String("select g from Group g left join fetch g.users u ");
Query query = session.createQuery(hql);
query.setFirstResult(startRow);
query.setMaxResults(pageSize);
List<Group> groups = query.list();
出现了上面的警告!
方式二:
List<Group> groups = new ArrayList<Group>();
String hql = new String("select g, u from Group g left join g.users u order by g.groupId ");
Query query = session.createQuery(hql);
ScrollableResults scrollCursor = query.scroll(ScrollMode.FORWARD_ONLY);
int index = 0;
Group group = null;
User user = null;
Integer groupId = null; //记住上一个Group标识
int count = 0;
int size = 0;
while ( scrollCursor.next() ) {
group = (Group) scrollCursor.get(0);
Integer groupIdTemp = group.getGroupId(); //用于判断是否是同一个Group
if ( index >= startRow ) {
user = (User) scrollCursor.get(1);
size = groups.size();
if ( groupIdTemp.equals(groupId) ) { //重复Group,往对应的Group添加role
if ( size > 0 ) { //当起始行不是0且该startRow-1的Group存在User集合时,过滤掉这些User
groups.get(size-1).getUsers().add(user);
}
} else { //Group不同时,把Group添加到list里
if ( index == (startRow+pageSize) ) break; //控制与pageSize相同
Set<User> users = new LinkedHashSet<User>();
if ( user != null ) {
users.add(user);
}
group.setUsers(users);
//记住最后一个的Group标识
groupId = group.getGroupId();
groups.add(group);
index++;
}
} else {
if ( !groupIdTemp.equals(groupId) ) {
//记住最后一个的Group标识
groupId = group.getGroupId();
index++;
}
}
if ( ++count%50 == 0 ) session.clear(); //清除已经结束的查询
}
scrollCursor.close();
自己用游标控制分页,但感觉这种方式效率上不是很好!
不知道有谁有更好的方法来解决这问题?
数据库sql server 2k
hibernate左外连接同时即时抓取集合并利用setMaxResults()和setFirstResult()进行分页会出现
WARN [main] QueryTranslatorImpl.list(328) | firstResult/maxResults specified with collection fetch; applying in memory!的警告
在hibernate实战一书中也提到这样的语句在语义上就是错的,并且hibernate会退回到在内存中现在结果
Query execution options that are based on the SQL result rows, such as pag-ination with setMaxResults()/setFirstResult(), are semantically incor-rect if a collection is eagerly fetched. If you have an eager fetched collectionin your query, at the time of writing, Hibernate falls back to limiting theresult in-memory, instead of using SQL.
举个例子:
Group和User是1:n
方式一:
String hql = new String("select g from Group g left join fetch g.users u ");
Query query = session.createQuery(hql);
query.setFirstResult(startRow);
query.setMaxResults(pageSize);
List<Group> groups = query.list();
出现了上面的警告!
方式二:
List<Group> groups = new ArrayList<Group>();
String hql = new String("select g, u from Group g left join g.users u order by g.groupId ");
Query query = session.createQuery(hql);
ScrollableResults scrollCursor = query.scroll(ScrollMode.FORWARD_ONLY);
int index = 0;
Group group = null;
User user = null;
Integer groupId = null; //记住上一个Group标识
int count = 0;
int size = 0;
while ( scrollCursor.next() ) {
group = (Group) scrollCursor.get(0);
Integer groupIdTemp = group.getGroupId(); //用于判断是否是同一个Group
if ( index >= startRow ) {
user = (User) scrollCursor.get(1);
size = groups.size();
if ( groupIdTemp.equals(groupId) ) { //重复Group,往对应的Group添加role
if ( size > 0 ) { //当起始行不是0且该startRow-1的Group存在User集合时,过滤掉这些User
groups.get(size-1).getUsers().add(user);
}
} else { //Group不同时,把Group添加到list里
if ( index == (startRow+pageSize) ) break; //控制与pageSize相同
Set<User> users = new LinkedHashSet<User>();
if ( user != null ) {
users.add(user);
}
group.setUsers(users);
//记住最后一个的Group标识
groupId = group.getGroupId();
groups.add(group);
index++;
}
} else {
if ( !groupIdTemp.equals(groupId) ) {
//记住最后一个的Group标识
groupId = group.getGroupId();
index++;
}
}
if ( ++count%50 == 0 ) session.clear(); //清除已经结束的查询
}
scrollCursor.close();
自己用游标控制分页,但感觉这种方式效率上不是很好!
不知道有谁有更好的方法来解决这问题?