多线程入库,部分线程抛出以下异常。org.hibernate.transaction.JDBCTransaction commit
严重: JDBC commit failed
java.sql.SQLException: commit() should not be called while in auto-commit mode.
at net.sourceforge.jtds.jdbc.ConnectionJDBC2.commit(ConnectionJDBC2.java:1878)
at org.jboss.resource.adapter.jdbc.local.LocalManagedConnection.jdbcCommit(LocalManagedConnection.java:781)
at org.jboss.resource.adapter.jdbc.local.LocalConnection.commit(LocalConnection.java:560)
at org.hibernate.transaction.JDBCTransaction.commitAndResetAutoCommit(JDBCTransaction.java:174)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:146)我在org.hibernate.transaction.JDBCTransaction.commitAndResetAutoCommit 中增加了日志,提交前,
检测到的jdbcContext.connection().getAutoCommit()还是false(后来证实ConnectionJDBC3 commit前,其状态是autocommit==true,而LocalConnection、LocalManagedConnection的 autocommit状态都为false,怎么会不一致呢????)。
commitAndResetAutoCommit 增加日志输出后,修改后代码为
"java"
private void commitAndResetAutoCommit() throws SQLException {
try {
Connection conn=jdbcContext.connection();
System.out.println("[DB]JDBCTransaction.commitAndResetAutoCommit conn.getAutoCommit="+conn.getAutoCommit()
+" conn'classname="+conn.getClass().getName()
+" conn'classURL="+conn.getClass().getResource(""));
conn.commit();
}
finally {
toggleAutoCommit();
}
}我的程序对HibernateTemplate 中的execute 中做了修改添加了事务的手动开启和提交(12、31行)
"java"    public Object execute(HibernateCallback action, boolean exposeNativeSession, String entityName)
            throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");        Session session = getSession();
        boolean existingTransaction = SessionFactoryUtils.isSessionTransactional(session, getSessionFactory());
        if (existingTransaction) {
            LOG.debug("Found thread-bound Session for HibernateTemplate");
        }        FlushMode previousFlushMode = null;  
        Transaction tx = session.beginTransaction();
        StringBuffer strbuff=new StringBuffer();
        String log;
        long threadid=Thread.currentThread().getId();
        try {        
         previousFlushMode = applyFlushMode(session, existingTransaction);
          enableFilters(session);
        
            Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));
            Object result = action.doInHibernate(sessionToExpose);            flushIfNecessary(session, existingTransaction);            tx.commit();
        }

解决方案 »

  1.   

    commit() should not be called while in auto-commit mode.不是多线程的问题吧。默认的是自动提交模式下。如果你需要手动提交,请在获取连接后添加如下代码:conn.setAutoCommit(false;
      

  2.   

    默认是自动提交,但是需要配制AOP事务管理
      

  3.   


    不过,我将所有的session.hashCode()都打印出来,发现每个线程中的session.hashCode()值都不一样,
    能不能认为每个线程都用了不同的session。况且如果将这个execute设置成线程同步,也就失去了多线程的意义了。
      

  4.   


    Transaction tx = session.beginTransaction();
    这句就已经将session.setAutoCmmmit(false)