Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [JDBC] Передача параметров в хранимку ORACLE, Работа с Callable statement 
V
    Опции темы
Girin
Дата 27.2.2010, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 6.2.2008

Репутация: нет
Всего: нет



Добрый день всем. Есть проблема : на сервере Оракл(10g) к которому идет обращение из DAO объекта, существует хранимая процедура,  имеющая следующую сигнатуру 
Код

procedure setMainParam(param1 IN VARCHAR2,param2 IN OUT NUMBER)

При вызове этой процедуры непосредственно из среды БД, например из блока PL/SQL хранимка нормально отрабатывает и возвращает через param2 выходное значение.

При использовании CallableStatement вылетает эксепшен
Код

 "ORA-06502 : буффер символьных строк слишком маленький ошибка числа или значения" 


Вызываю следующим образом:
Код

//connection получен ранее
CallableStatement cstmt=con.prepareCall("{call myschema.setMainParam(?,?)}");
cstmt.setString(1,'STOP');
cstmt.setInt(2,1);
cstmt.registerOutPutParameter(2,OracleTypes.NUMBER);
cstmt.execute();//здесь генерится эксепшен

Перепробовал различные варианты типа регистрируемого выходного параметра - не помогает.
В чем может быть проблема ? 

з.ы.
Прошу прощения если тема больше относится к разделу Oracle и если я ошибся топиком, но в контексте самой СУБД такой ошибки не возникает
PM   Вверх
MaxPayneC
Дата 27.2.2010, 18:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 18.2.2006

Репутация: 3
Всего: 9



Какой JDBC-драйвер вы используете?
И еще, что такое "parameter in out number"? Я не очень шарю в оракле, действительно ли для таких параметров надо делать и сетИнт, и регистерАутПараметер?
И третье, что меня смутило - неуказание размера варчара и намбера. Попробуйте их указать, ибо ошибка 06502 чаще всего вызывается проблемами конвертации и присвоения данных.

Это сообщение отредактировал(а) MaxPayneC - 27.2.2010, 18:16
PM   Вверх
jk1
Дата 27.2.2010, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 5
Всего: 75



MaxPayneC, 
IN OUT означает, что параметр передается в хранимую процедуру, модифицируется и возвращается, конструкция легальна. Надо регистрировать дважды, как входной и как выходной. В этом отношении все выглядит правильно.

Girin, 
Меня больше смущает 
Код

cstmt.setString(1,'STOP');

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


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
Girin
Дата 27.2.2010, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 6.2.2008

Репутация: нет
Всего: нет



Цитата(jk1 @ 27.2.2010,  21:36)
Girin, 
Меня больше смущает 
Код

cstmt.setString(1,'STOP');

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

jk1,  да Вы правы ошибка компиляции имеет место, варировал фактические параметры и  при постинге сообщения скопировал с одинарными кавычками случайно набраное значение. 

MaxPayneC , точную версию драйвера надо уточнить на рабочем компе, помню что использую тот который идет в стандартной поставке с клиентом Oracle 10.2.0(ojdbc14.jar). По поводу размера типов меня тоже посетила мысль, возможно умолчальные значения точности оракловых и jdbc типов различны - спасибо за совет проверю эту версию. 

PM   Вверх
MaxPayneC
Дата 27.2.2010, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 18.2.2006

Репутация: 3
Всего: 9



ojdbc14.jar предназначен для JDK 1.4. Если я ошибаюсь насчет длин параметров - попробуйте скачать драйвер под вашу версию оракла и вашу версию ЖДК.
PM   Вверх
jk1
Дата 27.2.2010, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 5
Всего: 75



Длина параметра здесь ни при чем.

Во-первых, в CallableStatement просто нет методов для её указания.
Во-вторых, мне ни разу не приходилось сталкиваться в необходимостью определять длину параметра для Oracle из Java.

Разве что вы в базе задали размер Varchar так, что ваши строки в него не лезут.


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
MaxPayneC
Дата 27.2.2010, 23:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 18.2.2006

Репутация: 3
Всего: 9



Женек, я имел в виду что вероятно, varchar2 имеет максимальную длину 0, или number короткий. Не уверен (
PM   Вверх
jk1
Дата 27.2.2010, 23:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 5
Всего: 75



Girin,  нашел еще вот такую мысль:

Рекомендуется присваивать значение in out параметру после регистрации, а не до нее, как это сделано у вас в коде.
http://www.cyberguru.ru/programming/visual...occi-page3.html




--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
Girin
Дата 2.3.2010, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 6.2.2008

Репутация: нет
Всего: нет



Цитата(jk1 @ 27.2.2010,  23:51)
Girin,  нашел еще вот такую мысль:

Рекомендуется присваивать значение in out параметру после регистрации, а не до нее, как это сделано у вас в коде.
http://www.cyberguru.ru/programming/visual...occi-page3.html

Да, спасибо почитал еще об этом - данный подход необязателен, но является рекомендацией в стиле good practice.

Проблема с ошибкой указанной выше решилась на уровне кода хранимки, где в возвращаемую переменную присваивалось  значение большее диапазона указаного при ее определении  

Столкнулся в контексте этого же топика с другой уже проблемой: 
После выполнения statement пытаюсь получить возвращаемое значение:
Код

cstmt.execute();
Integer res=cstmt.getInt(2);
 
В  итоге переменную res возвращается 0. В отладчике у cstmt есть protected поле - parameterInt хранимое как массив, и как я заметил второй элемент этого поля хранит правильное возвращаемое значение, а первое как раз 0. 
Как можно правильно извлечь реально возращаемое IN OUT  значение?
PM   Вверх
Girin
Дата 2.3.2010, 17:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 6.2.2008

Репутация: нет
Всего: нет



Извиняюсь, все нормально работает. Причина в самой хранимке. Просьба к модераторам удалить последнее сообщение. Тема решена

Это сообщение отредактировал(а) Girin - 2.3.2010, 17:35
PM   Вверх
DimW
Дата 9.3.2010, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1330
Регистрация: 24.2.2005
Где: Орёл

Репутация: 3
Всего: 44



Цитата(Girin @  2.3.2010,  17:35 Найти цитируемый пост)
Просьба к модераторам удалить последнее сообщение. Тема решена

на мой взгляд решена путем костылизации.
рекомендую пользоваться монятными типами и методами для использования конкретной БД, если вы конечно не загоняетесь на тему кроплатформенности использования СУБД, хотя использование хранимки говорит, что не загоняетесь smile 

накидал для вас пример, в нем используются IN, OUT и IN OUT параметры, и три самых распространенных в использовании типа данных в оракл.

хранимка:
Код

create or replace procedure my_test(p_param_1 in number 
                                   ,p_param_2 out varchar2
                                   ,p_param_3 in out date) is
begin
  p_param_2 := 'value_' || p_param_1;
  p_param_3 := p_param_3 + 1;
end my_test;


ее вызов:
Код

package javaapplication4;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import oracle.jdbc.OracleCallableStatement;

public class Main {

    private static void execMyOracleProc() throws SQLException
    {
        DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
        String connStr = "jdbc:oracle:thin:test/test@testDB:1521:testSID";
        Connection conn = DriverManager.getConnection(connStr);
        OracleCallableStatement stmt;
        stmt = (OracleCallableStatement)conn.prepareCall("begin " +
                                                                   "my_test(p_param_1 => ?" +
                                                                           ",p_param_2 => ?" +
                                                                           ",p_param_3 => ?);" +
                                                                "end;");

        //
        BigDecimal pNumber = new BigDecimal(100);
        String pVarchr2 = null;
        java.util.Date pDate = new java.util.Date();
        
        // передаю p_param_1
        stmt.setNUMBER(1, new oracle.sql.NUMBER(pNumber));

        // регистрирую p_param_2
        stmt.registerOutParameter(2, oracle.jdbc.OracleTypes.VARCHAR);

        // передаю p_param_3, поскольку он IN OUT
        stmt.setDate(3, new java.sql.Date(pDate.getTime()));
        // регистрирую p_param_3, поскольку он IN OUT
        stmt.registerOutParameter(3, oracle.jdbc.OracleTypes.DATE);

        stmt.execute();

        pVarchr2 = stmt.getString(2);
        pDate = stmt.getDate(3);

        System.out.println("-------------------------");
        System.out.println("p_param_1 = " + pNumber); // исходный параметр
        System.out.println("p_param_2 = " + pVarchr2); // результат конкитенации с p_param_1
        System.out.println("p_param_3 = " + pDate); // должен быть + 1 день
        System.out.println("-------------------------");

        stmt.close();
        conn.close();
    }

    public static void main(String[] args) throws SQLException {
        execMyOracleProc();
    }
}


хоть и не своевременно, но думаю будет полезно smile

Это сообщение отредактировал(а) DimW - 9.3.2010, 16:00
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0750 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.