今天在一个DAO中尝试对一个数据执行先查询再更新的操作,结果后台提示出现了sql语句
Hibernate: select group_id from fnd_groupid where id= ?
Hibernate: update fnd_groupid set group_id= ? where id = ?
本来是很简单的一个操作,但是数据库里面的值却始终不更新。
之前的代码如下:
SQLQuery query = this.getSession().createSQLQuery("select group_id from fnd_groupid where id= ?"); query.setLong(0, 1L); Long nextVal = StringTools.parseLong(query.uniqueResult().toString()); SQLQuery queryUpdate = this.getSession().createSQLQuery("update fnd_groupid set group_id= ? where id = ? "); queryUpdate.setLong(0, nextVal+1); queryUpdate.setLong(1, 1l); queryUpdate.executeUpdate();
后来google一下,才发现我的操作很有问题,我连续取出当前会话进行操作,前面的查询操作可以进行,但是此时会话还在进行中,我后面再次取到当前会话,并执行更新操作,这个操作始终无法完成。多次操作应该使用事务,只有提交事务之后才会生效。这其中涉及到hibernate的一级缓存机制。
这说明埋头写代码真的没啥用,原理的东西很多尚待研究,任重而道远~~
修改后的代码如下:
Session session = this.getSession(); Transaction transaction = session.beginTransaction();//启动事务 SQLQuery query = session.createSQLQuery("select group_id from fnd_groupid where id= ?"); query.setLong(0, 1L); Long nextVal = StringTools.parseLong(query.uniqueResult().toString()); SQLQuery queryUpdate = session.createSQLQuery("update fnd_groupid set group_id= ? where id = ? "); queryUpdate.setLong(0, nextVal+1); queryUpdate.setLong(1, 1l); queryUpdate.executeUpdate(); transaction.commit(); session.close(); return nextVal;
与Hibernate DetachedCriteria有关的分页问题
这是本人做项目数据库移植的时候遇到的一个最典型的问题,在查询总量的时候,会报如下错误
ORDER BY 子句中的列 "fnd_code.CODE_ID" 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中。
当时百度google了很久,感觉网上都是泛泛而谈,没有从根源解决这个问题。下面就这个问题分析一下。
public List findPageByCriteria(DetachedCriteria criteria, int pageFirst, int pageMax){ log.debug("finding instance page by criteria"); try { List results = getHibernateTemplate().findByCriteria(criteria, pageFirst, pageMax); log.debug("find page by criteria successful, page size: " + results.size()); return results; } catch (RuntimeException re) { log.error("find page by criteria failed", re); throw re; } }
这是BaseDao中的一个方法,使用hibernate管理数据库连接的时候,就是通过下面几行代码
getHibernateTemplate().findByCriteria(criteria, pageFirst, pageMax); //其中,criteria是查询语句,pageFirst就是要查第几页,而pageMax就是总页数,hibernate会自动将这一页的内容取出来
来进行分页查询的。
但是在进行分页查询以前,必须要知道记录总数,以及分页信息,这个通常手动指定。知道这些信息后,再通过记录总数调整分页信息,调整方法如下:
public void adjustByTotalRow(int total){ totalRow = total; if(totalRow < 1){ page = 0; //当前页 pageRow = 0; //页面记录数 totalPage = 0;//总页数 totalRow = 0;//总数据量 } else { //设置总页数 totalPage = (totalRow / pageMax) + ((totalRow % pageMax) == 0 ? 0 : 1); //调整页号 if(page > totalPage){ page = totalPage; } else if(page < 1){ page = 1; } //计算页面记录数 pageRow = totalRow - (page - 1) * pageMax; if (pageRow > pageMax){ pageRow = pageMax; } } }
下面问题出来了,需要获得记录总数,最简单的代码如下所示
select count(*) from fnd_code order by code_id
但是令人蛋碎的是,一模一样的一个sql语句,在oracle中正常运行,但是sql server竟然报错,就是我上面贴出来的这个错误。分页的问题就是因为这个语句出来的。
在我的service中,进行如下调用,需要说明的是,现在传进来的criteria是有order的。
protected List findByPage(BaseDAO dao, DetachedCriteria criteria, PageMeta page) throws ServiceException{ if (page == null) { return dao.findByCriteria(criteria); } else { int total = dao.findTotalByCriteria(criteria);//获取记录总数 if (total == 0) { // no record found return null; } page.adjustByTotalRow(total);//这个方法上面有贴出来,调整分页信息 // fetch the result page if (page.getPage() < 1) { // no fetch needed return null; } List results = dao.findPageByCriteria(criteria,page.getPageFirstRow(), page.getPageMax());//分页查询 }
在service中,获取记录总数就会调用上面类似的sql语句,错误也就在此产生的。
啰嗦这么多,只是想也把分页的方法大致描述一下,方便理解。这个问题解决起来很简单,我们要把addOrder操作加到获取记录总数之后。下面是我修改的BaseService
protected Order order;//定义一个字段Order /*此方法供外部调用,不再给criteria添加Order,而是将order给service */ public void addOrder(Order order){ this.order = order; } protected List findByPage(BaseDAO dao, DetachedCriteria criteria, PageMeta page) throws ServiceException{ if (page == null) { return dao.findByCriteria(criteria); } else { int total = dao.findTotalByCriteria(criteria); if (total == 0) { // no record found return null; } if(order != null){ criteria.addOrder(order);//获取记录总数以后,再将order加入 } // adjust the page meta info by the actual total page.adjustByTotalRow(total); // fetch the result page if (page.getPage() < 1) { // no fetch needed return null; } List results = dao.findPageByCriteria(criteria,page.getPageFirstRow(), page.getPageMax()); }
作了如下调整后,分页问题不复存在,当然我的方法可能不太好,如果哪位朋友有不同解决办法,可以留言交流,谢谢。
今天处理日期时发现一个问题,日期越减越大,为啥?
原来是基本数据类型的问题,Java默认数值类型为int型,下面的运算超出范围,越界之后数值变为负数,因此出现这个问题。
sDate.setTime(eDate.getTime() - 180*24*60*60*1000);
应该在后面加上类型转换:
sDate.setTime(eDate.getTime() - 180*24*60*60*1000 L);
这种类型的错误太蛋疼了~~