Как я могу выполнить хранимую процедуру с JDBC / jTDS без использования транзакции? - PullRequest
0 голосов
/ 26 июля 2010

Мы запустили веб-сайт, написанный на Java, который использует JDBC с jTDS для доступа к базе данных SQL Server.

Наша база данных содержит сложную хранимую процедуру, которая обычно занимает 10 минут. Хранимая процедура работает нормально, если мы выполняем ее напрямую (например, из SQL Server Management Studio), поскольку она не выполняется в транзакции. Но если мы выполним его с использованием jTDS, он заблокирует весь веб-сайт на 10 минут. Это происходит потому, что jTDS запускает его в транзакции, и поэтому все запросы веб-сайта находятся в ожидании, пока транзакция завершится.

Например, из-за транзакции сайт блокируется следующим образом:

Connection connection = DriverManager.getConnection("jdbc:jtds:sqlserver://example/example");
CallableStatement callableStatement = connection.prepareCall("exec dbo.procTest");
callableStatement.execute();

Есть ли способ запустить хранимую процедуру с использованием JDBC / jTDS без ее выполнения в транзакции?

Обратите внимание, что вызов этого соединения через jTDS недействителен:

connection.setTransactionIsolation(Connection.TRANSACTION_NONE);

Это вызывает исключение, указывающее, что параметр Connection.TRANSACTION_NONE не поддерживается jTDS.


РЕДАКТИРОВАТЬ: Вероятно, я мог бы задать вопрос лучше: основная проблема не в самой транзакции, а в том, что транзакция заставляет блокировки базы данных удерживаться в течение 10 минут. Либо мне нужно избавиться от транзакции , либо мне нужно блокировок, снятых во время транзакции .

Ответы [ 3 ]

1 голос
/ 07 декабря 2018

В нашем случае нужно было вызвать StoredProcedure, который вызывал исключение при вызове из jtds:

Невозможно выполнить операцию резервного копирования или восстановления в транзакции.

Что я нашел @ https://communities.bmc.com/docs/DOC-66239 Требуется ли предварительный вызов exec с "SET IMPLICIT_TRANSACTIONS OFF;"

Вот как выглядит фрагмент на основе пружины:

try {
  jdbcTemplate.getJdbcOperations.execute("SET IMPLICIT_TRANSACTIONS OFF;")
  //noinspection ConvertExpressionToSAM   // we have 1.6 code version
  jdbcTemplate.getJdbcOperations.call(new CallableStatementCreator {
    override def createCallableStatement(con: Connection): CallableStatement = {
      val callableStatement = con.prepareCall(
        s""" EXEC dbo.RestoreLatestCopy
           |      @ID = ?
           |""".stripMargin)
      callableStatement.setInt(1, getMappedRestoreId(fromDbName))
      callableStatement
    }
  }, parameters ++ rsParams)
} catch {
0 голосов
/ 28 июля 2010

В итоге я использовал следующий уродливый обходной путь. Мне все еще интересно, если кто-нибудь может объяснить, как я мог бы сделать это правильно; но обходной путь подойдет на данный момент.

База данных работает на том же компьютере на веб-сервере, поэтому я могу использовать стандартные инструменты командной строки SQL Server для запуска хранимой процедуры. Код Java для его запуска:

    try {
        Process process = Runtime.getRuntime().exec("sqlcmd -E -d \"example\" -Q \"EXEC dbo.procTest;\"");
        process.waitFor();
    } catch (IOException e) {
        // Handler here
    } catch (InterruptedException e) {
        // Handler here
    }

Таким образом, выполняется точно такая же хранимая процедура - разница в том, что веб-сервер не блокируется, потому что sqlcmd не выполняет его в одной транзакции. Да, это уродливо ... но это единственный известный мне вариант, который работает!

0 голосов
/ 26 июля 2010

Вызов Connection#close() или Connection#commit() должен отправить и завершить транзакцию.Вы закрываете ресурсы БД, такие как Connection в блоке finally?

...