Вызов хранимой процедуры Oracle с возвратом нескольких строк из Spring - PullRequest
0 голосов
/ 29 ноября 2018

Я работаю над приложением, использующим Java, Eclipse и Spring.У нас есть база данных Oracle, к которой мы подключаемся с использованием JDBC.

В настоящее время приложение использует запросы adhoc в приложении к базе данных.Большинство из них были сделаны людьми, работающими над проектом, прежде чем я пришел вместе.Я решил, что использование хранимых процедур - лучший способ.Развязка для другого слоя абстракции.Не нужно каждый раз отправлять оператор sql, что снижает пропускную способность и ускоряет транзакции.Oracle может оптимизировать их в отличие от adhoc.Изменения в них могут происходить без необходимости перекомпиляции, если входные и выходные данные не меняются.Все эти замечательные вещи.

Adhoc-запросы часто возвращают несколько строк и используют интерфейс rowMapper и mapRow

 return jdbcTemplate.query(sql, new adhoc_mapper1());

class adhoc_mapper1 implements RowMapper<List<String>> {
    public List<String> mapRow(ResultSet rs, int arg1) throws SQLException{
    ArrayList<String> arr1 = new ArrayList<String>();
    arr1.add(rs.getString("OUT_POSITION_ID"));
    arr1.add(rs.getString("OUT_POSITION_TITLE_EN"));

    return arr1;
    }
}

Adhoc Query in Spring

 SELECT     HR.POSITION_ID,     HR.POSITION_TITLE_EN,   HR.POSITION_TITLE_FR,   HR.SECURITY_ID,     HR.GROUP_NAME,  HR.GROUP_LEVEL,     HR.POSITION_IS_ACTIVE
    FROM HR_POSITION HR JOIN DRILL_POSITION DP ON (HR.POSITION_ID = DP.POSITION_ID) 
WHERE DP.TYPEVALUE = RECORD_TYPE;

ВызываетсяПроцедура в Oracle

CREATE OR REPLACE PROCEDURE DOCSADM.DRILL_RECORD_POSITION (
    RECORD_TYPE IN VARCHAR2,
    OUT_POSITION_ID OUT VARCHAR2,
    OUT_POSITION_TITLE_EN OUT VARCHAR2,
    OUT_POSITION_TITLE_FR OUT VARCHAR2,
    OUT_SECURITY_ID OUT VARCHAR2,
    OUT_GROUP_NAME OUT VARCHAR2,
    OUT_GROUP_LEVEL OUT VARCHAR2,
    OUT_POSITION_IS_ACTIVE OUT VARCHAR2
) AS
BEGIN
    SELECT  HR.POSITION_ID,     HR.POSITION_TITLE_EN,   HR.POSITION_TITLE_FR,   HR.SECURITY_ID,     HR.GROUP_NAME,  HR.GROUP_LEVEL,     HR.POSITION_IS_ACTIVE
    INTO    OUT_POSITION_ID,    OUT_POSITION_TITLE_EN,  OUT_POSITION_TITLE_FR,  OUT_SECURITY_ID,    OUT_GROUP_NAME, OUT_GROUP_LEVEL,    OUT_POSITION_IS_ACTIVE
    FROM HR_POSITION HR JOIN DRILL_POSITION DP ON (HR.POSITION_ID = DP.POSITION_ID) WHERE DP.TYPEVALUE = RECORD_TYPE;
END DRILL_RECORD_POSITION;

Как видите, процедура возвращает несколько строк.Я задал вопрос о том, как просмотреть выходные данные процедуры в Oracle, но не удалось.

Поскольку в проекте не используются вызываемые процедуры, у меня нет примеров в базе кода дляработать обратно.Один из моих коллег, участвующих в другом проекте, использовал их и был достаточно любезен, чтобы показать мне их пример, который, к сожалению, не помог, потому что он вызывал только процедуру и не имел возврата.Их общий дизайн также выглядит иначе.Но я увидел, что они используют SimpleJdbcCall, поэтому я начал искать в Интернете, чтобы использовать это.

Хорошие примеры в Интернете, с которыми мне не удалось работать.

Я нашел примеры, которые былиделать то, что мне нужно было сделать, но не совсем так, как я ожидал.

  1. Этот пример соответствует тому, что я ожидал увидеть и использовать, за исключением того, что в результате он принимает только одну строку, и я не смог понятьКак изменить отображение, чтобы принять несколько строк.
  2. В этом примере используется процедура, которая возвращает несколько строк, но она использует ParameterizedBeanPropertyRowMapper и передает класс.
  3. В этом примере есть несколько способов выполнить эти вызовы, но все они возвращаются в одну строку, но комментарии к комментариям действительно предполагают, что его легко расширить для нескольких строк.Но я опять не смог заставить его работать.

Я не хочу создавать класс для каждой процедуры или семейства процедур.Большинство запросов в конечном итоге отображают информацию в таблице, поэтому я использовал двумерный объект для хранения, а затем для отображения данных.Это было очень удобно до сих пор.Я в порядке с созданием сопоставления для каждой процедуры, поскольку это необходимо сделать (если нет лучшего способа?), Но я не хочу создавать класс для каждой процедуры (а иногда и сопоставителя).

У меня есть 150 строк неудачных попыток кода, которые я не включил, чтобы сократить вопрос.Если они помогут, я могу их включить.

TL; DR Я хочу вызвать хранимую процедуру в Oracle из Spring, в которой возвращено несколько строк.Я хотел бы использовать только вызывающую функцию, которая либо использует метод отображения RowMapper, либо отображение в функции.Я хочу избежать использования структур классов данных, если это возможно.Я ожидаю / надеюсь, что это будет выглядеть и привыкнуть как первый блок кода.

1 Ответ

0 голосов
/ 03 декабря 2018

В моей методологии для этого есть основная ошибка.Способ, которым я пытался вернуть несколько строк, неверен.Как указано кем-то в моем связанном вопросе.Таким образом, способы, которыми я пытался получить к нему доступ, также были неправильными.Когда я ограничил возврат одной строкой, следующее было успешным:

Сначала импорт

import java.sql.Connection;
import java.sql.CallableStatement;

Затем вызов

 final String procedureCall = "{call DRILL_RECORD_POSITION(?, ?, ?, ?, ?, ?, ?, ?)}";

      try (Connection connection = jdbcTemplate.getDataSource().getConnection();) 
      {
          ArrayList<String> inner = new ArrayList<String>();
          CallableStatement callableSt = connection.prepareCall(procedureCall);
          callableSt.setString(1, "D");

          callableSt.registerOutParameter(2, Types.VARCHAR);
          callableSt.registerOutParameter(3, Types.VARCHAR);
          callableSt.registerOutParameter(4, Types.VARCHAR);
          callableSt.registerOutParameter(5, Types.VARCHAR);
          callableSt.registerOutParameter(6, Types.VARCHAR);
          callableSt.registerOutParameter(7, Types.VARCHAR);
          callableSt.registerOutParameter(8, Types.VARCHAR);

          //Call Stored Procedure
          callableSt.executeUpdate();

          for (int i=2; i<9; i++)
          {
               System.out.println(callableSt.getString(i));
          }
      }catch (SQLException e) {
        e.printStackTrace();
      }

Обратите внимание, что я используюпопробуйте использовать ресурсы, чтобы мне не пришлось беспокоиться о закрытии соединения.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...