这段时间在做一个叫“香港自由行”的项目,是一个旅游网站。我负责的模块是景点页面,主要是星级评分、评论、查附件5个景点。功能很简单,做的时候也没啥大问题。
但是,某天,在我提交确认无误提交后,发现另外一人做的上传景点功能一直报500。遂找了那位队友问了一下,原来是他之前改了数据库表的两个字段的类型但是我没更新么,于是删了数据库表更新跑了一下项目……然后问题就这么来了
查询景点评论的时候每条评论都查了四遍= =||| 而且因为用了hibernate的分页查询,每次查10条记录,也导致了部分评论因此没查询到(如下图)
然后我凌乱了QAQ 提交之后没改过代码啊!!怎么突然就出问题……T T
于是开始debug,从Controller一直debug到service层,后来发现执行完dao层的方法后拿到的List里面的数据已经重复了。
当时用的dao层是ken哥写好的,也没去怀疑是dao层出问题了,所以debug了一晚上,改了无数种形式,还是没行。
代码:
Service层:
Scenery scenery = this.getScenery(scenery_id);
Criterion cirterion = Restrictions.eq("scenery", scenery);
currentPageSceneryCommentList = sceneryCommentDao.findByPageSize(firstRecord, pageSize, Order.desc("date"), cirterion);
dao层:
@SuppressWarnings("unchecked")
@Override
public List<T> findByPageSize( int first, int pageSize, Order orderType,Criterion... criterions)
{
Session session = sessionFactory.getCurrentSession();
Criteria criteria = session.createCriteria(entityClass)
.setFirstResult(first)
.setMaxResults(pageSize);
if(orderType != null)
criteria.addOrder(orderType);
for(Criterion criterion : criterions)
{
criteria.add(criterion);
}
return criteria.list();
}
之后实在没办法,于是找华哥T^T……华哥说:“你的那个评论表叫业生重新设计,把那个集合list改为set就不会有这样的问题了。至于dao层那里用list为什么会出错,我暂时也猜不到”
然后找了业生……评论表没改,讨论了很久为什么会这样,这时候,起鹏过来了……问:“什么问题搞了这么久啊?”
结果起鹏一语破的的说:“左外关联,我以前做督导的时候也遇到过这个问题,dao层的方法有问题。”因此评论表关联了其它表,才出现的这种问题……默默地抹一把泪,坑了一晚上居然是dao层出错么!
然后起鹏在dao的方法上加了点东西,曰:“这样就能把重复的去掉”,如下:
Criteria criteria = session.createCriteria(entityClass)
.setFirstResult(first)
.setMaxResults(pageSize)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
满心欢喜地刷新页面~结果……
重复的确实去掉了,但是查询的时候仍然有查了……部分评论没有查询到的情况依然存在,每页也显示不到10条评论。
然后又尝试了将
.setMaxResults(pageSize)
这一行放最后,显然是没成功,因为不存在优先级问题。
最后得出的结论是……还是自己拼hql语句算了T.T
dao层:
public List<SceneryComment> findSceneryCommentByPageSize(int firstRecord, int pageSize, String scenery_id)
{
Session session = sessionFactory.getCurrentSession();
String hql = "from SceneryComment sc where sc.scenery.scenery_id='"+scenery_id+"'order by sc.date desc";
Query q = session.createQuery(hql).setFirstResult(firstRecord).setMaxResults(pageSize);
List<SceneryComment> list = new ArrayList<SceneryComment>();
list = q.list();
return list;
}
这么一来问题是解决了,但是……不甘心啊不甘心!捉摸着怎么改dao层或者调个其它的方面不成么?!
第二天下午又尝试了下dao层的其它方法,还真给发现了一个……
service层:
Scenery scenery = this.getScenery(scenery_id);
DetachedCriteria criteria = DetachedCriteria.forClass(SceneryComment.class)
.add(Restrictions.eq("scenery", scenery))
.setFetchMode("scenery", FetchMode.LAZY)
.addOrder(Order.desc("date"));
currentPageSceneryCommentList = sceneryCommentDao.findByCriteria(criteria, firstRecord, pageSize);
dao层:
@SuppressWarnings("unchecked")
@Override
public List<T> findByCriteria(final DetachedCriteria criteria, final int firstResult, final int maxResults)
{
Session session = sessionFactory.getCurrentSession();
Criteria executableCriteria = criteria.getExecutableCriteria(session);
if (firstResult >= 0) {
executableCriteria.setFirstResult(firstResult);
}
if (maxResults > 0) {
executableCriteria.setMaxResults(maxResults);
}
return executableCriteria.list();
}
关键在于
.setFetchMode("scenery", FetchMode.LAZY)
这一句吧
不过最后提交上去的还是用了自己拼hql语句的方法。
经过这件事,其实觉得还是自己拼sql语句的好。
即使是用hibernate,因为要开启事务,而且hql最终还是要转换成sql,速度上没有原始的sql语句来得快。
在做大作业的时候用的sql,后来暑假学了三大框架,改大作业的时候用了hql,小伙伴们也一众觉得hql没有sql快。
以上只是为了记录一下第一次做项目被坑的经历lol