Contents | Prev | Next | Главная страница JDBCTM Guide: Getting Started


7 - Класс CallableStatement (вызываемый оператор)

7.1    Введение

Объект CallableStatement предоставляет унифицированный способ вызова хранимых процедур в любой СУБД. Вызов процедуры осуществляется с помощью escape-синтаксиса в одной из двух форм: с результирующим параметром и без него. (См. раздел 4, "Запрос (Statement)" об escape-синтаксисе). Результирующий параметр - это один из типов выходных (OUT) параметров, являющийся возвращаемым значением хранимой процедуры. Обе формы могут иметь переменное число аргументов на входе (параметры IN), выходе (параметры OUT) или входных и выходных параметров одновременно (INOUT-параметры). Вопросительный знак означает местоположение параметра.

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

    {call имя_процедуры[(?, ?, ...)]}
Синтаксис для процедуры, возвращающей результат:

    {? = call имя_процедуры[(?, ?, ...)]}
Синтаксис хранимой процедуры без параметров:

    {call имя_процедуры}
Обычно тот, кто использует объект CallableStatement, уже знает, что используемая СУБД поддерживает хранимые процедуры и какие именно процедуры имеются в БД. Тем не менее, чтобы это выяснить, достаточно вызвать некоторые методы объекта DatabaseMetaData. Например, метод supportsStoredProcedures возвращает true, если СУБД поддерживает хранимые процедуры, а метод getProcedures возвращает описания доступных процедур.

CallableStatement наследует методы Statement общей для обработки SQL-запросов, а также методы PreparedStatement для обработки входных (IN) параметров. Все методы, объявленные в CallableStatement обрабатывают выходные (OUT) параметры следующим образом: указание JDBC-типов данных (т.е. SQL-типов) выходных параметров, извлечение из них значений или проверка их на NULL.

7.1.1     Создание объекта CallableStatement

Объекты CallableStatement создаются методом prepareCall объекта Connection. Приведем пример, который создает экземпляр CallableStatement, содержащий вызов хранимой процедуры getTestData с двумя аргументами и без возвращаемого параметра:

    CallableStatement cstmt = con.prepareCall(
                  "{call getTestData(?, ?)}");
Какими именно параметрами (IN, OUT или INOUT) являются знаки вопроса - зависит от самой хранимой процедуры getTestData.

7.1.2     IN- и OUT-параметры

Передача значений входных парметров объекта CallableStatement осуществляется с помощью методов setXXX, унаследованных от PreparedStatement. Типы передаваемых значений определяются тем, какой из методов setXXX используется (setFloat для передачи значений float и т.п.).

JDBC-типы всех OUT-параметров хранимых процедур должны быть зарегистрирваны перед их вызовом. Это необходимо, так как некоторым СУБД нужно передавать информацию и типах данных. Регистрация типов данных выходного параметра производится методом registerOutParameter. Только в этом случае после выполнения запроса методы getXXX класса CallableStatement смогут получить значения параметров. Необходимо использовать подходящий по типу данных Java метод getXXX в соответствии с зарегистрированным JDBC-типом параметра. (Стандартное отображение типов из JDBC в Java показано в таблице раздела 8.6.1.) Другими словами, registerOutParameter использует JDBC-тип (тот, который подходит к JDBC-типу возвращаемого из БД значения), а getXXX преобразует его в тип Java.

Приведем пример регистрации выходных параметров, выполнения хранимой процедуры cstmt и считывание выходных параметров. Метод getByte извлекает байт из первого выходного параметра, а getBigDecimal возвращает объект BigDecimal (с тремя цифрами после десятичной точки) из второго:

    CallableStatement cstmt = con.prepareCall(
                          "{call getTestData(?, ?)}");
    cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
    cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3);
    cstmt.executeQuery();
    byte x = cstmt.getByte(1);
    java.math.BigDecimal n = cstmt.getBigDecimal(2, 3);
В отличие от ResultSet, CallableStatement не может считывать большие значения последовательно (в потоке).

7.1.3     Параметры INOUT

В случае параметра, который одновременно является и входным, и выходным (INOUT), необходимо вызывать как соответствующий метод setXXX (унаследованный от PreparedStatement), так и метод registerOutParameter. Метод setXXX устанавливает входное значение параметра, а registerOutParameter регистрирует тип выходного значения.

Типы входного и выходного значений, зарегистрированных методом registerOutParameter, должны быть одинаковыми. Для чтения выходного значения используется соответствующий метод getXXX. Например, для параметра типа byte нужно использовать метод установки значения setByte, передавать JDBC-тип данных TINYINT методу registerOutParameter и использовать getByte для чтения выходного значения. (В разделе 8 "Отображение типов JDBC на типы Java" приведена более подробная информация о соответствии типов данных).

В следующем примере вызывается хранимая процедура reviseTotal с единственным INOUT-параметром. Метод setByte устанавливает значение параметра в 25, которое будет представлено базе данных как TINYINT. Далее метод registerOutParameter регистрирует параметр как TINYINT. После выполнения хранимой процедуры возвращается значение типа TINYINT, которое будет считано методом getByte в виде типа byte языка Java.

    CallableStatement cstmt = con.prepareCall(
        "{call reviseTotal(?)}");
    cstmt.setByte(1, 25);
    cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
    cstmt.executeUpdate();
    byte x = cstmt.getByte(1);

7.1.4     Считывайте выходные(OUT) параметры после считывания результатов

Из-за ограничений некторых СУБД для большей совместимости рекомендуется сначала считывать результаты, сгенерированные вызовом CallableStatement, а затем выходные (OUT) параметры.

Если объект CallableStatement возвращает несколько объектов ResultSet (с использованием метода execute), то ВСЕ результаты должны быть прочитаны перед первым обращением к выходным параметрам. В этом случае для того, чтобы прочитать все результаты, надо последовательно вызывать методы Statement getResultSet, getUpdateCount и getMoreResults до тех пор, пока не останется больше результатов.

После этого значения выходных параметров могут быть извлечены спомощью методов CallableStatement.getXXX.

7.1.5     Возвращение значения NULL в выходных параметрах

Значение, возвращенное в выходной параметр, может быть NULL. При этом методы getXXX возвращают null, 0 или false, в зависимости от типа данных. Как и в случае с ResultSet, единственным способом узнать, вернула ли процедура 0, false или NULL, является вызов метода wasNull, который возвращает true, если последнее значение, считанное одним из методов getXXX был NULL, и false иначе. См. раздел 5, "ResultSet (набор данных)".

    


Содержание | Предыдущий | Следующий