2015-12-18 2 views
1

У меня проблема, код ниже работает нормально, если я запускаю его без свойства autoCommit, однако я бы предпочел запустить его как транзакцию, в основном код вставляет информацию заголовка статьи, а затем список всех связанных с ним статей (так что это как отношение «один ко многим»), поэтому я хотел бы совершить все за один раз, а не сначала информацию о статье, а затем ее элементы. Проблема в том, что, когда я достигаю к линии cn.commit(), я получаю исключение, которое говорит «закрытое заявление»java.sql.SQLException Закрытое заявление

метод вставки базы данных

public static void addArticle(Article article) throws SQLException { 
      Connection cn = null; 
      PreparedStatement ps = null; 
      StringBuffer insert = new StringBuffer(); 
      StringBuffer itemsSQL = new StringBuffer(); 

      try { 
        article.setArticleSortNum(getNextArticleNum(article.getShopId())); 
        article.setArticleId(DAOHelper.getNextId("article_id_sequence")); 

        cn = DBHelper.makeConnection(); 
        cn.setAutoCommit(false); 

        insert.append("insert query for article goes here"); 
        ps = cn.prepareStatement(insert.toString()); 
        int i = 1; 
        ps.setLong(i, article.getArticleId()); i++; 
        ps.setLong(i, article.getShopId()); i++; 
        ps.setInt(i, article.getArticleNum()); i++; 
        // etcetera... 
        ps.executeUpdate(); 

        itemsSQL.append("insert query for each line goes here"); 
        itemStatement = cn.prepareStatement(itemsSQL.toString()); 
        for(Article item : article.getArticlesList()) { 

         item.setArticleId(article.getArticleId()); 
         i= 1; 
         itemStatement.setLong(i, item.getArticleId()); i++; 
         itemStatement.setInt(i, item.getItemsOnStock()); i++; 
         itemStatement.setInt(i, item.getQuantity()); i++; 
         // etcetera... 
         itemStatement.executeUpdate(); 

        } 
        cn.commit(); 

      } catch (SQLException e) { 
        cn.rollback(); 
        log.error(e.getMessage()); 
        throw e; 
      } 
      finally { 
        DBHelper.releasePreparedStatement(ps); 
        DBHelper.releasePreparedStatement(itemStatement); 
        DBHelper.releaseConnection(cn); 
      } 
     } 

Я также имел вставку пунктов, где для является запускается с помощью addBatch(), затем executeBatch, но также и с той же ошибкой Closed Statement при достижении cn.commit() ... Я не понимаю, почему его закрытие, все соединения и все выпущено в предложении finally, поэтому я получаю ощущение, что я делая некоторую фундаментальную ошибку, о которой я не знаю ... Любые идеи? Заранее спасибо!

EDIT: Ниже трассировки стека:

java.sql.SQLException: Закрытое Заявление на oracle.jdbc.dbaccess.DBError.throwSqlException (DBError.java:189) в oracle.jdbc. dbaccess.DBError.throwSqlException (DBError.java:231) при oracle.jdbc.dbaccess.DBError.throwSqlException (DBError.java:294) при oracle.jdbc.driver.OracleStatement.ensureOpen (OracleStatement.java:6226) на oracle.jdbc.driver.OraclePreparedStatement.sendBatch (OraclePreparedStatement.java:592) по адресу oracle.jdbc.driver.OracleConnection.commit (OracleConnection.java:1376) at com.evermind.sql.FilterConnection.commit (FilterConnection.java:201) at com.evermind.sql.OrionCMTConnection.commit (OrionCMTConnection. java: 461) at com.evermind.sql.FilterConnection.commit (FilterConnection.java:201) at com.dao.ArticlesDAO.addArticle (ArticlesDAO.java:571) в com.action.registry.CustomBaseAction.execute (CustomBaseAction.java:57) на org.apache.struts.action.RequestProcessor.processActionPerform (RequestProcessor.java:431) на org.apache.struts.action.RequestProcessor.process (RequestProcessor.java:236) на org.apache.struts.ac tion.ActionServlet.process (ActionServlet.java:1196) at org.apache.struts.action.ActionServlet.doPost (ActionServlet.java:432) at javax.servlet.http.HttpServlet.service (HttpServlet.java:760) при javax.servlet.http.HttpServlet.service (HttpServlet.java:853) при com.evermind.server.http.ServletRequestDispatcher.invoke (ServletRequestDispatcher.java:765) на com.evermind.server.http. ServletRequestDispatcher.forwardInternal (ServletRequestDispatcher.java:317) на com.evermind.server.http.HttpRequestHandler.processRequest (HttpRequestHandler.java:790) на com.evermind.server.http.HttpRequestHandler.run (HttpRequestHandler.java: 270) в com.evermind.server.http.HttpRequestHandler.run (HttpRequestHandler.java:112) в com.evermind.util.ReleasableResourcePooledExecutor $ MyWorker.run (ReleasableResourcePooledExecutor.java:192) в java.lang.Thread.пробег (Unknown Source)

EDIT 2:

Эти параметры источника данных конфигурации водителя, я думал, что процесс отладки может делать это время, но даже заняв менее чем второй бросает закрытое заявление исключение

min-connections="20" 
max-connections="200" 
inactivity-timeout="20" 
stmt-cache-size="40"/> 
+0

Можете ли вы отправить полный стек исключения? – zerocool

+0

Я отредактировал вопрос и добавил трассировку стека – Ricardo

ответ

2

это, как правило, лучше создать заявление, использовать его и закрыть его как можно скорее, и это не делает никакого вреда сделать это до того, как транзакция получает обязательство Тед. От чтения Oracle tuturial о пакетной модели звучит так, будто может возникнуть проблема одновременного открытия нескольких операторов. Я хотел бы попробовать закрыть объект пс перед началом работы с itemStatement, затем переместив инициализацию

itemStatement = cn.prepareStatement(itemsSQL.toString()); 

непосредственно выше для цикла, а также двигаться, где вы закрываете itemStatement сразу после того, как цикл:

PreparedStatement itemStatement = cn.prepareStatement(itemsSQL.toString()); 
try { 
    for(Article item : article.getArticlesList()) { 
     item.setArticleId(article.getArticleId()); 
     i= 1; 
     itemStatement.setLong(i, item.getArticleId()); i++; 
     itemStatement.setInt(i, item.getItemsOnStock()); i++; 
     itemStatement.setInt(i, item.getQuantity()); i++; 
        // etcetera... 
     itemStatement.executeUpdate(); 
    } 
} finally { 
    DBHelper.releasePreparedStatement(itemStatement); 
} 

Похоже, что происходит то, что у вас есть определенный параметр пакетного соединения, который вызывает соединение, чтобы попытаться найти незавершенный бизнес в заявлении для завершения; он находит заявление уже закрытым, и связь жалуется на него. Это странно, потому что в момент, когда котировка взорвется на вас, код не достиг окончательно, где утверждение закрывается.

Возможно, полезно ознакомиться с моделью дозирования Oracle. Также проверьте версию драйвера JDBC и убедитесь, что она подходит для версии Oracle, которую вы используете, и посмотрите, есть ли у нее какие-либо обновления.

+0

Это действительно выглядело так, как будто это сработает! Но я получил только одно и то же исключение :( – Ricardo

+0

Я обновил параметры таймаута/подключений, в конфигурационном файле – Ricardo

+0

@Ricardo: хорошо. Посмотрите, полезно ли мое обновление. Также, если у вас есть более подробная информация о пакетной обработке кода или конфигурация для подключения, пожалуйста, добавьте их в вопрос. –

Смежные вопросы