Как выполнить анонимный PL / SQL из Java с помощью jdbctemplate - PullRequest
0 голосов
/ 10 июня 2019

Я хочу вызвать этот запрос (который работает при запуске на SQL-разработчике) из Java

DECLARE
    TYPE my_id_tab IS
        TABLE OF my_table.my_id%TYPE;
    my_ids  my_id_tab;
BEGIN
    UPDATE my_table
        SET
            another_id = NULL
    WHERE
        another_id IS NULL
        AND   create_datetime BETWEEN '03-JUN-19' AND '05-JUN-19'
    RETURNING my_id BULK COLLECT INTO my_ids;

    COMMIT;
END;

Но я полагаю, что Java испытывает трудности с попыткой выяснить, хочу ли я вернуть коллекцию my_ids мне.

Вот что я пробовал до сих пор с сообщениями об исключениях типа java.sql.SQLException: Invalid column index или же java.sql.SQLException: operation not allowed: Ordinal binding and Named binding cannot be combined!

final Connection connection = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());

      try (final CallableStatement callableStatement = connection.prepareCall(TEST_SQL))
      {
         callableStatement.registerOutParameter("my_ids", Types.ARRAY);
         callableStatement.executeUpdate();
         int[] arr = (int[]) callableStatement.getArray("my_ids").getArray();
         return Arrays.stream(arr).boxed().collect(Collectors.toSet());
      }
      catch (final SQLException e)
      {
         LOG.info("threw exception, {}", e);
      }
      finally
      {
         DataSourceUtils.releaseConnection(connection, jdbcTemplate.getDataSource());
      }

1 Ответ

0 голосов
/ 11 июня 2019

Это не самая простая вещь, но это довольно легко сделать.Вам нужно будет создать ТИП в Oracle для определения результатов.

Для этой демонстрации создайте и заполните EMP и DEPT: Сценарии EMP и DEPT

Создайте TYPE, необходим для определения возвращаемого массива:

create type t_integer_array as table of integer;

Мы запустим следующий UPDATE, который обновит только несколько строк:

UPDATE emp
   SET job = job        -- a nonsense update
 WHERE comm IS NOT NULL -- only affect some of the rows

Здесьтакое Java:

package test;

import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Types;
import java.util.Arrays;

public class OracleTest {

  public static void main(String[] args) {
    try {
      Class.forName("oracle.jdbc.driver.OracleDriver");
      Connection conn = DriverManager.getConnection(
              "<your JDBC url>", "<your user>", "<your password>");

      // Prepare the call, without defining the the output variable
      // in a DECLARE section of the PL/SQL itself, you just need to
      // include a "?" and then associate the correct type in the
      // next step.
      CallableStatement cs = conn.prepareCall(
                "BEGIN\n"
              + "  UPDATE emp\n"
              + "     SET job = job\n"
              + "   WHERE comm is not null\n"
              + "  RETURNING empno BULK COLLECT INTO ?;\n"
              + "END;");

      // Register the single OUT parameter as an array, using the 
      // type that was defined in the database, T_INTEGER_ARRAY.
      cs.registerOutParameter(1, Types.ARRAY, "T_INTEGER_ARRAY");
      cs.execute();

      // Now get the array back, as array of BigDecimal.
      // BigDecimal is used because it doesn't have precision 
      // problems like floating point, it will contain all digits
      // that the database provided.
      BigDecimal[] nums = (BigDecimal[]) (cs.getArray(1).getArray());
      System.out.println(Arrays.toString(nums));
      cs.close();
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}

А вот мой вывод:

[7499, 7521, 7654, 7844]

Это технические ключи(empno) только для тех строк, на которые повлияло обновление.

...