该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-08-25
破碎虚空 和 yangbo9229 遇到的的确是个问题,不知道为什么大家都没有注意到他们的话呢?
我来说一下我调试下来的观点: 在robin的HibernateCallback()内,不论先做count计算,还是先做list查询,都有问题。 robbin原来的代码:先count,然后用的setProjection(null),再查询,不过经测试,查出来的都是Object[],而不是原先DetachedCriteria.forClass(xxx)的内容了。 samuel_bai提到把两者的顺序换一下即可,但是换了以后照样有问题: 就是setFirstResult和setMaxResults的值还保留在criteria里面,查询count的时候,导致count变小,甚至出错(在查不到数据的时候,调用Integer.intValue()报NullPointException)。 我最后想了两个办法解决, 1: 采用robbin的顺序,不过取size的时候用的是: int totalCount = getHibernateTemplate().findByCriteria(detachedCriteria).size(); so ez?但是这样比较消耗内存,但是不用调用HibernateCallback的那段了,不用设置projection,后面的查询问题迎刃而解,整个代码看起来很清爽: int totalCount = getHibernateTemplate(); .findByCriteria(detachedCriteria);.size();; List<T> list = getHibernateTemplate();.findByCriteria(detachedCriteria, startIndex, pageSize);; return new PageInfo<T>(list, totalCount, pageSize, startIndex);; 2: 采用samuel_bai的顺序,先查询list,后设置count,这样setProjection的代码就跑到最后去了,可以不用设置了,自然也没有问题。但是pageSize, startIndex的问题怎么办呢? 没办法,我选择了一种很土的办法: criteria.setFirstResult(0);; criteria.setMaxResults(999);; 呵呵,大家别笑,至少是可行的了。 以上,就是我认真看完整个帖子后,郁闷了n小时后,蹩出来的一点点东西,大家笑纳。 |
|
返回顶楼 | |
发表时间:2006-09-08
昨天看到这篇帖子,学习了一整天,感觉受益非浅。
不过始终有一点疑问,这样做的话WEB层就会出现Hibernate的API了,这是不是有点违背分层的思想啊? |
|
返回顶楼 | |
发表时间:2006-09-12
public TokenStream tokenStream(String fieldName, Reader reader) { LetterTokenizer tokenizer = new LetterTokenizer(reader); TokenStream result = null; result = new LowerCaseFilter(tokenizer); result = new StopFilter(result, StopAnalyzer.ENGLISH_STOP_WORDS); result = new PorterStemFilter(result); return result; } } |
|
返回顶楼 | |
发表时间:2006-09-13
建议让hibernate重写.size 方法
太浪费代码了。。。。。 或者有我没发现么? |
|
返回顶楼 | |
发表时间:2006-09-15
条理很清晰滴说
|
|
返回顶楼 | |
发表时间:2006-09-15
downpour 写道 连续看了两篇robbin有关DetachedCriteria的介绍,感觉真的不错,尤其是上面的示例代码,让我着实觉得该对我原来的分页查询做一下代码重构了。
public class UserDAOImpl extends BaseDAOHibernateImpl implements UserDAO { public List getUserByName(String name) throws HibernateException { String querySentence = "FROM user in class com.adt.po.User WHERE user.name=:name"; Query query = getSession().createQuery(querySentence); query.setParameter("name", name); return query.list(); } public int getUserCount() throws HibernateException { int count = 0; String querySentence = "SELECT count(*) FROM user in class com.adt.po.User"; Query query = getSession().createQuery(querySentence); count = ((Integer)query.iterate().next()).intValue(); return count; } public List getUserByPage(Page page) throws HibernateException { String querySentence = "FROM user in class com.adt.po.User"; Query query = getSession().createQuery(querySentence); query.setFirstResult(page.getBeginIndex()) .setMaxResults(page.getEveryPage()); return query.list(); } } 每次都getSession(),怎么没有见关闭Session的语句? |
|
返回顶楼 | |
发表时间:2006-09-25
楼上的,session关闭是写在另外一个地方的.你没有看到getSession()方法也没有写如何获取session的吗?
|
|
返回顶楼 | |
发表时间:2006-12-12
downpour 写道 连续看了两篇robbin有关DetachedCriteria的介绍,感觉真的不错,尤其是上面的示例代码,让我着实觉得该对我原来的分页查询做一下代码重构了。
我把原本我的做法也提供出来供大家讨论吧: 首先,为了实现分页查询,我封装了一个Page类: /*Created on 2005-4-14*/ package org.flyware.util.page; /** * @author Joa * */ public class Page { /** imply if the page has previous page */ private boolean hasPrePage; /** imply if the page has next page */ private boolean hasNextPage; /** the number of every page */ private int everyPage; /** the total page number */ private int totalPage; /** the number of current page */ private int currentPage; /** the begin index of the records by the current query */ private int beginIndex; /** The default constructor */ public Page(){ } /** construct the page by everyPage * @param everyPage * */ public Page(int everyPage){ this.everyPage = everyPage; } /** The whole constructor */ public Page(boolean hasPrePage, boolean hasNextPage, int everyPage, int totalPage, int currentPage, int beginIndex) { this.hasPrePage = hasPrePage; this.hasNextPage = hasNextPage; this.everyPage = everyPage; this.totalPage = totalPage; this.currentPage = currentPage; this.beginIndex = beginIndex; } /** * @return * Returns the beginIndex. */ public int getBeginIndex() { return beginIndex; } 这样就可以通过配置文件和OGNL的共同作用来对page对象设置初值了。并可以通过随意修改配置文件来修改每页需要显示的记录数。 注:上面的<param>的配置,还需要webwork和Spring整合的配合。 有查询条件怎么办? |
|
返回顶楼 | |
发表时间:2006-12-15
sakis 写道 samuel_bai 写道 引用 Criteria criteria = detachedCriteria.getExecutableCriteria(session);
这段代码有如下几个问题:
int totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue(); criteria.setProjection(null); List items = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list(); 1。如果cirteria设置了projection,这里将其改变,那么查出的items则是不正确的。因此只要将tocalcount和items的位置换一下即可了 2。如果criteria设置了order的话,那么criteria生成的sql将会有语法错误,比如order by中的某某字段不在聚合函数中,如果能将criteria的order去掉就好了,可是criteria没有这个api...... - 1.cirteria设置了projection统计完rowCount后又setProjection(null),所以“基本”上应该是可行的。 - 2.这个order问题的确很伤心,我的做法是将Order[]作为一个参数传入,在rowCount统计完成后,再在criteria中加入。 这种分页做法很优美,完全把分页程序与具体表分离了,复用性很高。遗憾的是DetachedCriteria/Criteria现在实现的还不是十分完善,比如: 我用的hibernate是3.0.5,发现多次使用同一个DetachedCriteria对象后,在作rowCount projection时会出错,返回null(可前几次都返回了正确的结果)。 该方法对于单表查询应该还是没多大问题的,对于某些复杂的查询条件需要做更多的测试。 cirteria设置了projection统计完rowCount后又setProjection(null),所以“基本”上应该是可行的。 事实是不可行的,不可行的原因在于多表查询确实会出现返回的List中是对象数组这种情况,所以确实应该调换Items和计算总数的位置,先查items,再进行总数查询,这样肯定是没有问题的 |
|
返回顶楼 | |
发表时间:2006-12-25
ahuaxuan 写道 sakis 写道 samuel_bai 写道 引用 Criteria criteria = detachedCriteria.getExecutableCriteria(session);
这段代码有如下几个问题:
int totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue(); criteria.setProjection(null); List items = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list(); 1。如果cirteria设置了projection,这里将其改变,那么查出的items则是不正确的。因此只要将tocalcount和items的位置换一下即可了 2。如果criteria设置了order的话,那么criteria生成的sql将会有语法错误,比如order by中的某某字段不在聚合函数中,如果能将criteria的order去掉就好了,可是criteria没有这个api...... - 1.cirteria设置了projection统计完rowCount后又setProjection(null),所以“基本”上应该是可行的。 - 2.这个order问题的确很伤心,我的做法是将Order[]作为一个参数传入,在rowCount统计完成后,再在criteria中加入。 这种分页做法很优美,完全把分页程序与具体表分离了,复用性很高。遗憾的是DetachedCriteria/Criteria现在实现的还不是十分完善,比如: 我用的hibernate是3.0.5,发现多次使用同一个DetachedCriteria对象后,在作rowCount projection时会出错,返回null(可前几次都返回了正确的结果)。 该方法对于单表查询应该还是没多大问题的,对于某些复杂的查询条件需要做更多的测试。 cirteria设置了projection统计完rowCount后又setProjection(null),所以“基本”上应该是可行的。 事实是不可行的,不可行的原因在于多表查询确实会出现返回的List中是对象数组这种情况,所以确实应该调换Items和计算总数的位置,先查items,再进行总数查询,这样肯定是没有问题的 楼上说的调换items和计算总数的位置是这样的吗? List items = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list(); criteria.setProjection(null); int totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue(); PaginationSupport ps = new PaginationSupport(items, totalCount, pageSize, startIndex); 如果是这样的话,我试了一下,出现空指针异常;如果不是这样的请给说明一下; 我用robbin的方法,对一个没有关联的表,好象没什么问题,但是,我做了一个one to one的映射后,如下使用: DetachedCriteria detachedCriteria=DetachedCriteria.forClass(SysUser.class); int pageSize=2; int startIndex=1; PaginationSupport ps=sysUserService.findPageByCriteria(detachedCriteria, pageSize, startIndex); if(ps!=null){ System.out.println(ps.getPageSize()); System.out.println(ps.getNextIndex()); System.out.println(ps.getPreviousIndex()); System.out.println(ps.getIndexes().length); System.out.println(ps.getTotalCount()); List list=ps.getItems(); for(int i=0;i<list.size();i++){ SysUser sysUser=(SysUser)list.get(i); System.out.println(sysUser.getUserid()); } } 映射文件如下: <class name="com.hengji.model.SysUser" table="SYS_USER" schema="SUGARCRM"> <id name="userid" type="java.lang.String"> <column name="USERID" length="50" /> <generator class="assigned" /> </id> <property name="password" type="java.lang.String"> <column name="PASSWORD" length="50" not-null="true" /> </property> <property name="createDate" type="java.util.Date"> <column name="CREATE_DATE" length="7" /> </property> <property name="updateDate" type="java.util.Date"> <column name="UPDATE_DATE" length="7" /> </property> <property name="roleId" type="java.lang.String"> <column name="ROLE_ID" length="20" /> </property> <property name="useFlag" type="java.lang.String"> <column name="USE_FLAG" length="1" not-null="true" /> </property> <one-to-one name="userInfo" cascade="all" class="com.hengji.model.UserInfo"/> </class> 这样查出的总数,没有什么问题,可是items是一个对象数组,应该是被分成了sysuser和userinfo两个对象了,我把他转化为sysuser时,报类型转换异常;请问大家这个问题该如何解决? |
|
返回顶楼 | |