关于getHibernateTemplate().iterate().next()

使用getHibernateTemplate().iterate().next()的时候报如下错误(只留下了错误的主体部分):
ERROR: Operation not allowed after ResultSet closed
Exception in thread "main" org.hibernate.exception.GenericJDBCException: could not get next iterator result
Caused by: java.sql.SQLException: Operation not allowed after ResultSet closed


以下是DAO类,没有使用注解事务.(以下只截取了部分代码)
@Repository("forumHibernateDao")
//@Transactional 
public class ForumHibernateDao extends BaseDao{
    public long getForumNum(){
        Object obj = getHibernateTemplate().iterate("select count(f.forumId) from Forum f").next();
        return (Long) obj;
    }
} 


先说结论:在调用getForumNum()方法的时候报文章开头的错误,在给DAO加上事务后就正常了。

下面看看代码为什么这样。

1.跳转到HibernateTemplate类Iterator<?> iterate()方法中。
public Iterator<?> iterate(final String queryString, final Object... values) throws DataAccessException {
        return (Iterator)this.executeWithNativeSession(new HibernateCallback<Iterator<?>>() {
            public Iterator<?> doInHibernate(Session session) throws HibernateException {
                Query queryObject = session.createQuery(queryString);
                HibernateTemplate.this.prepareQuery(queryObject);
                if(values != null) {
                    for(int i = 0; i < values.length; ++i) {
                        queryObject.setParameter(i, values[i]);
                    }
                }

                return queryObject.iterate();
            }
        });
    }


2. 接着执行HibernateTemplate类的executeWithNativeSession(HibernateCallback<T> action),再执行doExecute(HibernateCallback<T> action, boolean enforceNativeSession),代码如下(重点看划线部分):

public <T> T executeWithNativeSession(HibernateCallback<T> action) {
        return this.doExecute(action, true);
    }

    protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNativeSession) throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");
        //初始化session
        [u]Session session = null;[/u]
        boolean isNew = false;

        try {
            //通过SessionFactory得到session, 此处所得session为null
            //如果有事务注解,则此处所得session非空
            [u]session = this.getSessionFactory().getCurrentSession();[/u]
        } catch (HibernateException var12) {
            this.logger.debug("Could not retrieve pre-bound Hibernate session", var12);
        }
        //如果有事务注解,则此处所得session非空判断,isNew仍未false
        if(session == null) {
            //session为空则open session.
            [u]session = this.getSessionFactory().openSession();[/u]
            session.setFlushMode(FlushMode.MANUAL);
            //设置isNew为true
            [u]isNew = true;[/u]
        }

        Object var6;
        try {
            this.enableFilters(session);
            Session sessionToExpose = !enforceNativeSession && !this.isExposeNativeSession()?this.createSessionProxy(session):session;
             //调用doInHibernate方法,进行持久化。
            [u]var6 = action.doInHibernate(sessionToExpose);[/u]
        } catch (HibernateException var13) {
            throw SessionFactoryUtils.convertHibernateAccessException(var13);
        } catch (RuntimeException var14) {
            throw var14;
        } finally {
            //isNew为true,所以此处关闭session.
            //如果有事务注解,isNew为false,session不会关闭。
            if(isNew) {
                SessionFactoryUtils.closeSession(session);
            } else {
                this.disableFilters(session);
            }

        }

        return var6;
    }



以上说明在无事务调用next()方法时, session已经关闭,所以在接着调用next()方法的时候抛出异常报错;而若存在事务,则session不会关闭,则可正确调用该方法。

猜你喜欢

转载自summerhome.iteye.com/blog/2384647