- 2010年12-5
今天在一个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;
- 2010-12-8
与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());
}
作了如下调整后,分页问题不复存在,当然我的方法可能不太好,如果哪位朋友有不同解决办法,可以留言交流,谢谢。
- 2010-12-14
今天处理日期时发现一个问题,日期越减越大,为啥?
原来是基本数据类型的问题,Java默认数值类型为int型,下面的运算超出范围,越界之后数值变为负数,因此出现这个问题。
sDate.setTime(eDate.getTime() - 180*24*60*60*1000);
应该在后面加上类型转换:
sDate.setTime(eDate.getTime() - 180*24*60*60*1000 L);
这种类型的错误太蛋疼了~~