Nano Hash - криптовалюты, майнинг, программирование

java.sql.SQLException Закрытое заявление

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

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

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);
             }
       }

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

РЕДАКТИРОВАТЬ: Ниже приведена трассировка стека:

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) на com.evermind.sql.FilterConnection.commit(FilterConnection.java:201) на com.evermind.sql.OrionCMTConnection.commit(OrionCMTConnection.java:461) на com.evermind.sql .FilterConnection.commit(FilterConnection.java:201) в 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.RequestProce ssor.process(RequestProcessor.java:236) в org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196) в org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) в 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.run (неизвестный источник)

РЕДАКТИРОВАТЬ 2:

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

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

  • Не могли бы вы опубликовать полную трассировку стека исключения? 19.12.2015
  • Я отредактировал вопрос и добавил трассировку стека 19.12.2015

Ответы:


1

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

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

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

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);
}

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

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

18.12.2015
  • Это действительно выглядело так, как будто это сработает! Но я только что получил точно такое же исключение :( 19.12.2015
  • Я обновил параметры тайм-аута/соединения, которые есть в файле конфигурации. 19.12.2015
  • @Рикардо: хорошо. посмотрите, полезно ли мое обновление. также, если у вас есть дополнительные сведения о пакетной обработке кода или конфигурации соединения, добавьте их в вопрос. 19.12.2015
  • Создание оператора внутри цикла for устраняет преимущество однократной подготовки и вместо этого вводит накладные расходы на каждую итерацию. 19.12.2015
  • @Mark: спасибо, я обновлю. есть идеи по поводу пакетной части? возможно ли, что сохранение оператора ps открытым, пока открыто itemstatement, вызывает проблему? просто мало информации по вопросу? 19.12.2015
  • Это не должно быть проблемой, когда autoCommit отключен. Я понятия не имею, почему код в вопросе терпит неудачу. Мне это кажется возможной ошибкой в ​​​​драйвере, но я не совсем уверен. 19.12.2015
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..