hibernate查询语句却报Could not execute JDBC batch update错误的原因追踪

本文分析了一个关于Hibernate在执行查询时出现的批量更新异常问题。该异常发生在使用list方法进行查询过程中,即使代码中未执行更新操作也会触发。通过深入源码发现,当查询涉及的对象处于游离状态时,Hibernate会尝试将更改flush到数据库,导致异常。
摘要由CSDN通过智能技术生成

业务系统在使用hibernate的list方法做查询时报了以下的一个错误:
org.hibernate.exception.DataException: Could not execute JDBC batch update,非常奇怪,我们当前的方法中并没有做更新操做和保存操作啊,怎么报了这样一个错误?于是顺着问题追了下去,主要是org.hibernate.impl.SessionImpl中的关键代码:

    public List list(String query, QueryParameters queryParameters) throws HibernateException {
        errorIfClosed();
        checkTransactionSynchStatus();
        queryParameters.validateParameters();
        HQLQueryPlan plan = getHQLQueryPlan( query, false );
        autoFlushIfRequired( plan.getQuerySpaces() );

        List results = CollectionHelper.EMPTY_LIST;
        boolean success = false;

        dontFlushFromFind++;   //stops flush being called multiple times if this method is recursively called
        try {
            results = plan.performList( queryParameters, this );
            success = true;
        }
        finally {
            dontFlushFromFind--;
            afterOperation(success);
        }
        return results;
    }

    /**
     * detect in-memory changes, determine if the changes are to tables
     * named in the query and, if so, complete execution the flush
     */
    protected boolean autoFlushIfRequired(Set querySpaces) throws HibernateException {
        errorIfClosed();
        if ( ! isTransactionInProgress() ) {
            // do not auto-flush while outside a transaction
            return false;
        }
        AutoFlushEvent event = new AutoFlushEvent(querySpaces, this);
        AutoFlushEventListener[] autoFlushEventListener = listeners.getAutoFlushEventListeners();
        for ( int i = 0; i < autoFlushEventListener.length; i++ ) {
            autoFlushEventListener[i].onAutoFlush(event);
        }
        return event.isFlushRequired();
    }

注意:第二个方法autoFlushIfRequired的注释意思是:在当前session中,如果发现有查询HQL涉及到的java对象在当前一级缓存中是游离状态,则会将其flush进数据库,如果在flush批处理的过程中出现问题,则会抛上边batch update的异常。这里要提到的是:如果是SQL查询就不会有这个问题,因为hibernate现在不从SQL倒推出SQL里表对应的java持久化对象,因此不会执行flush操作。 总结一句话:使用开源工具,有刁钻问题网上查不到就直接进源码,很多源码里都有明确清晰的注释,让人恍然大悟。以上说的可能不够全面,算是抛砖引玉了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值