powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / FAQ: Java & Oracle, передача-прием массивов.
18 сообщений из 18, страница 1 из 1
FAQ: Java & Oracle, передача-прием массивов.
    #32872455
Фотография Denis Popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Взято с Metalink .

При работе через THIN-драйвер отсутствует возможность передачи -приема pl/sql таблиц Oracle. Но можно воспользоваться оракловыми объектными типами.

Код, который необходимо выполнить на сттороне Oracle:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
create or replace type rectype as object (
    cnumber   number ( 9 )
  , cvarchar  varchar2 ( 32  char)
  , cdate     date
)
/
create or replace type rectab as table of rectype;
/
create or replace package iostructarray as
  procedure testproc (
      iorec in out rectab
    , orec out rectab
  );
end;
/
create or replace package body iostructarray as
  procedure testproc (
      iorec in out rectab
    , orec out rectab
  ) is
  begin
    -- Копирование inout параметра в out и изменение inout параметра.
    orec := iorec;
    for i in  1  .. iorec.count loop
      iorec (i).cnumber := -orec (i).cnumber;
      iorec (i).cvarchar := 'New-' || orec (i).cvarchar;
      iorec (i).cdate := orec (i).cdate +  1  +  12  /  24  +  34  / ( 24  *  60 ) +  56  / ( 24  *  60  *  60 );
    end loop;
  end;
end;
/

Демонстрация работы с массивами:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
 import  oracle.jdbc.driver.OracleCallableStatement;
 import  oracle.jdbc.driver.OracleTypes;
 import  oracle.sql.ARRAY;
 import  oracle.sql.ArrayDescriptor;
 import  oracle.sql.STRUCT;
 import  oracle.sql.StructDescriptor;

 import  java.sql.Connection;
 import  java.sql.DriverManager;
 import  java.sql.SQLException;
 import  java.sql.Timestamp;
 import  java.util.ArrayList;
 import  java.util.Calendar;

 public   class  CallableStructArray {

   private   static   final  String username = "hall";
   private   static   final  String password = "h";
   private   static   final  String URL = "jdbc:oracle:thin:@192.168.170.90:1521:CVPROC";

   public   static   void  main(String[] args)
     throws  SQLException {
    DriverManager.registerDriver( new  oracle.jdbc.driver.OracleDriver());
    // Коннект к Oracle.
    Connection con = DriverManager.getConnection(URL, username, password);
    // Определяем два дескриптора, для ARRAY TYPE и для OBJECT TYPE.
    StructDescriptor structDesc = StructDescriptor.createDescriptor("RECTYPE", con);
    ArrayDescriptor arrayDesc = ArrayDescriptor.createDescriptor("RECTAB", con);

    // Инициализация коллекции для объектов STRUCT.
    ArrayList pArrayList =  new  ArrayList();

    // Объявление массива для значений.
    // Размерность его равна количеству атрибутов в объектном типе RECTYPE,
    // присвоение значений будет идти в порядке объявления в объектном типе.
    Object[] pRecord =  new  Object[ 3 ];
    // Определение значений и создание объекта STRUCT.
    pRecord[ 0 ] =  new  Integer( 1 );
    pRecord[ 1 ] = "Первый";
    pRecord[ 2 ] =  new  Timestamp(Calendar.getInstance().getTimeInMillis());
    pArrayList.add( new  STRUCT(structDesc, con, pRecord));

    pRecord[ 0 ] =  new  Integer( 2 );
    pRecord[ 1 ] = "Второй";
    pRecord[ 2 ] =  new  Timestamp(Calendar.getInstance().getTimeInMillis());
    pArrayList.add( new  STRUCT(structDesc, con, pRecord));

    // Создание объекта ARRAY.
    ARRAY pARRAY =  new  ARRAY(arrayDesc, con, pArrayList.toArray());
    // Объявление callable statement.
    // Он должен быть объявлен как OracleCallableStatement.
    OracleCallableStatement cst = (OracleCallableStatement) con.prepareCall(
      "{call ioStructArray.testproc(iorec=>?, orec=>?)}"
    );
    // Определение первого параметра процедуры
    cst.setARRAY( 1 , pARRAY);
    // Первый параметр имеет тип inout, поэтому дополнительно он регистрируется как out.
    // Note the reuse of the TYPE.
    cst.registerOutParameter( 1 , OracleTypes.ARRAY, "RECTAB");
    // Регистрация второго out-параметра процедуры
    cst.registerOutParameter( 2 , OracleTypes.ARRAY, "RECTAB");
    // Выполнение процедуры
    cst.execute();

    // Ассоциация возвращаемого массива с объектом ARRAY.
    pARRAY = cst.getARRAY( 1 );
    // Получение данных первого параметра.
    Object[] pObjects = (Object[]) pARRAY.getArray();
    System.out.println("Первый объект:");
     for  ( int  i =  0 ; i < pObjects.length; i++) {
      pRecord = ((STRUCT) pObjects[i]).getAttributes();
      System.out.println(pRecord[ 0 ] + " | " + pRecord[ 1 ] + " | " + pRecord[ 2 ]);
    }

    // Получение данных второго параметра.
    pARRAY = cst.getARRAY( 2 );
    pObjects = (Object[]) pARRAY.getArray();
    System.out.println("Второй объект:");
     for  ( int  i =  0 ; i < pObjects.length; i++) {
      pRecord = ((STRUCT) pObjects[i]).getAttributes();
      System.out.println(pRecord[ 0 ] + " | " + pRecord[ 1 ] + " | " + pRecord[ 2 ]);
    }
  }
}
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #32872810
Фотография Timm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно дополнить и описать использование Custom Object Classes for Oracle Objects (завтра может напишу). Но есть глюк , от которого избавиться не удалось.
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #32874010
Фотография Timm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пусть имеются вышеописанные типы rectype и rectab.
Код: plaintext
1.
2.
3.
4.
5.
6.
SQL> desc rectab
 rectab TABLE OF RECTYPE
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- -----------------
 CNUMBER                                                                    NUMBER( 9 )
 CVARCHAR                                                                   VARCHAR2( 32  CHAR)
 CDATE                                                                      DATE
Для работы с этим типом как с обычным java-классом можно использовать:
1) стандартный интерфейс SQLData;
2) оракловые интерфейсы ORAData и ORADataFactory.
Опишу второй способ.
1) Для генерации java-классов, которые будут представлять оракловые типы, удобно воспользоваться утилитой JPublisher ([ORACLE_HOME]/bin/jbub.exe). Необходимо прописать следующие пути: [ORACLE_HOME]/jdbc/lib/classes12.zip; [ORACLE_HOME]/sqlj/lib/runtime12.zip and [ORACLE_HOME]/sqlj/translator.zip; [ORACLE_HOME]/jdbc/lib/nls_charset12.zip
2) Создаем файл jprop.txt:
jpub.driver=oracle.jdbc.driver.OracleDriver
jpub.numbertypes=oracle
jpub.url=jdbc:oracle:thin:@localhost:1521:info
jpub.builtintypes=oracle
jpub.user=tim/t
jpub.sql=rectab

3) В командной строке:
Код: plaintext
1.
2.
c:\Work\code>jpub -props=jprop.txt
TIM.RECTAB
TIM.RECTYPE
В результате получаем два файла с необходимыми классами: rectab.java и Rectype.java (эстеты могут переименовать классы в RecTab и RecType соответственно:))
4)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
 import  oracle.jdbc.driver.OracleCallableStatement;
 import  oracle.jdbc.driver.OracleTypes;
 import  oracle.sql.*;

 import  java.sql.*;
 import  java.io.*;
 import  java.util.Calendar;

 public   class  CallableStructArray {

	 private   static   final  String username = "tim";
	 private   static   final  String password = "t";
	 private   static   final  String URL = "jdbc:oracle:thin:@localhost:1521:info";

	 public   static   void  main(String[] args)  throws  SQLException {
		 try  {
			System.setOut( new  PrintStream(System.out, true, "cp866"));
		}  catch  (Exception e) {
		} //try
		DriverManager.registerDriver( new  oracle.jdbc.driver.OracleDriver());
		Connection conn = DriverManager.getConnection(URL, username, password);

		OracleCallableStatement ocstmt = (OracleCallableStatement)conn.prepareCall(
			"BEGIN ioStructArray.testproc(?, ?); END;");

		//get character set
		 int  oracleId = CharacterSet.CL8MSWIN1251_CHARSET;
		CharacterSet myCharSet = CharacterSet.make(oracleId);
		
		//construct array of rectype
		Rectype[] r =  new  Rectype[] {
			 new  Rectype( new  NUMBER( 1 ),  new   CHAR ("Первый", myCharSet),
				 new  DATE( new  Timestamp(Calendar.getInstance().getTimeInMillis()))),
			 new  Rectype( new  NUMBER( 2 ),  new   CHAR ("Второй", myCharSet),
				 new  DATE( new  Timestamp(Calendar.getInstance().getTimeInMillis())))};
		//construct table
		rectab tab =  new  rectab(r);
		
		ocstmt.setORAData( 1 , tab);
		ocstmt.registerOutParameter( 1 , OracleTypes.ARRAY, "RECTAB");
		ocstmt.registerOutParameter( 2 , OracleTypes.ARRAY, "RECTAB");

		ocstmt.execute();

		tab = (rectab)ocstmt.getORAData( 1 , rectab.getORADataFactory());
		r = tab.getArray();
		 for  ( int  i =  0 ; i<r.length; i++) {
			System.out.println(r[i].getCnumber().intValue() + "|" +	r[i].getCvarchar() + "|"
				+ r[i].getCdate().toText("YYYY.MM.DD HH24:MI:SS", "AMERICAN_AMERICA.CL8MSWIN1251"));
		} //for

		tab = (rectab)ocstmt.getORAData( 2 , rectab.getORADataFactory());
		r = tab.getArray();
		 for  ( int  i =  0 ; i<r.length; i++) {
			System.out.println(r[i].getCnumber().intValue() + "|" + r[i].getCvarchar() + "|"
				+ r[i].getCdate().toText("YYYY.MM.DD HH24:MI:SS",  "AMERICAN_AMERICA.CL8MSWIN1251"));
		} //for

	}
};
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #32879855
Фотография Denis Popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Timm: я свою часть предложил в разделе FAQ, предложи свою:)
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #32879885
Фотография А.Грасоff™
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Denis Popov2Timm: я свою часть предложил в разделе FAQ, предложи свою:)на всякий: фак опубликован, но, думаю, что не стоит
удалять одноименные топики (как этот, например) из форума -
яндекс и гугл пусть посетителей увеличивают :)
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #32903035
DrewT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
TimmМожно дополнить и описать использование Custom Object Classes for Oracle Objects (завтра может напишу). Но есть глюк , от которого избавиться не удалось.

От этого глюка избавиться можно, если поставить orai18n.jar и classes12.jar из 10g .
Кроме того, проблемы с выводом русских букв не останется если использовать BLOB, как это показано здесь .
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33090617
йцукен
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А подходят ли драйвера от 10g к базам на oracle 8i и 9i. У меня при их использовании вываливается ошибка

ORA-12705: invalid or unknown NLS parameter value specified

хотя установлено

set NLS_LANG=AMERICAN_AMERICA.CL8MSWIN1251
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33090648
Фотография Denis Popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
йцукенА подходят ли драйвера от 10g к базам на oracle 8i и 9i

У меня после наката пача Oracle 9.2.0.6 перестал работать возврат курсоров из хранимых процедур при использовании JDBC от 10g.
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33090687
йцукен
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Denis Popov[У меня после наката пача Oracle 9.2.0.6 перестал работать возврат курсоров из хранимых процедур при использовании JDBC от 10g.

А как ты запустил клиента?
Дело в том, что он у меня вообще не поднимается с этими драйверами.
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33090791
Фотография Denis Popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
йцукенА как ты запустил клиента?
Дело в том, что он у меня вообще не поднимается с этими драйверами.

Запустил и все:) Ни с какой ошибкой при "запуске" (т.е. при создании соединения?) не столкнулся. М.б. из-за того, что у нас все базы созданы в юникоде, а это порой избавляет от многих проблем.
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33090807
йцукен
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Denis Popov[Запустил и все:) Ни с какой ошибкой при "запуске" (т.е. при создании соединения?) не столкнулся. М.б. из-за того, что у нас все базы созданы в юникоде, а это порой избавляет от многих проблем.

Ну тогда конечно, у меня база в 1251
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33432838
verter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделал всё по написанному выше:

в java на строчке

pArrayList.add(new STRUCT(structDesc, con, pRecord));

вываливается ошибка:

java.sql.SQLException: Non supported character set: oracle-character-set-171
at oracle.gss.util.NLSError.throwSQLException(NLSError.java:46)
at oracle.sql.CharacterSetUnknown.failCharsetUnknown(CharacterSetFactoryThin.java:171)
at oracle.sql.CharacterSetUnknown.convert(CharacterSetFactoryThin.java:135)
at oracle.sql.CHAR.<init>(CHAR.java:159)
at oracle.sql.CHAR.<init>(CHAR.java:183)
at oracle.jdbc.oracore.OracleTypeCHAR.toDatum(OracleTypeCHAR.java:161)
at oracle.sql.StructDescriptor.toOracleArray(StructDescriptor.java:830)
at oracle.sql.StructDescriptor.toArray(StructDescriptor.java:1735)
at oracle.sql.STRUCT.<init>(STRUCT.java:145)


БД 8.1.7
NLS_NAME = AMERICAN_AMERICA.CL8MSWIN1251

Причём задаю для структуры не русские буквы, английские слова пишу
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33433162
Фотография Denis Popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nls_charset12.zip в CLASSPATH есть?
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33433540
verter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да есть. Я вообще в сервлете всё это делаю, а сервлет запускается на Tomcat'е. Эту библиотеку nls_charset.zip я положил вместе с остальными в Tomcat\common\lib\
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33433581
verter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
причём, я посмотрел, что в этой библиотеке nls_charset12.zip есть класс

oracle\sql\converter\CharacterConverter00ab.class

00ab = 171

наверное который работает с этим чарсетом.

после компиляции все библиотеки правильно лежат для Томкэта:

в

%Tomcat%\webapps\Имя_приложения\WEB-INF\lib\

но всё-равно ошибка вылетает.
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33433651
Фотография Denis Popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Локально тоже не работает? Что возвращает запрос?
Код: plaintext
select * from sys.props$ where name like 'NLS%CHARACTERSET';
И еще: какой именно используется JDBC-драйвер к Ораклу, имя файла?
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33433703
Фотография Denis Popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
FAQ: Java & Oracle, передача-прием массивов.
    #33433868
verter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Денис, спасибо за помощь!

решил проблему:

оказывается надо было использовать более свежую nls_charset12.zip, вернее nls_charset12.jar.

Я брал эту библиотеку для 8-ой версии оракла - не работало, взял для 9-ки - всё стало работать.
...
Рейтинг: 0 / 0
18 сообщений из 18, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / FAQ: Java & Oracle, передача-прием массивов.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]