Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / JAVA & Oracle collections / 1 сообщений из 1, страница 1 из 1
06.12.2004, 11:52
    #32814059
Ora-мучитель
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JAVA & Oracle collections
Необходимо выполнить хранимую процедуру на JAVA (на PL/SQL SAX-парсера
нет). Результатом ее работы будут три коллекции объектов. Чтобы не усложнять,
в качестве примера приведу упрощенный вариант на примере одной коллекции,
который ясно демонстрирует возникшую проблему. Элементом коллекции является
объект с двумя полями - числовым и строкой. Вызов идет из PL/SQL. Но между
вызовом и возвратом данных проходит 5-10 секунд (для коллекции размером 50000
элементов).

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
-- Создаю тестовый вариант объекта и коллекции 
create or replace type testObj as object
(
  id number( 16 ),
  value varchar2( 30 )
);

create or replace type testObjs as table of TestObj;

С использованием JPublisher генерирую классы-оболочки для объекта и
коллекции.

Код: 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.
// для объекта testobj
 package  pack_new;

 import  java.sql.SQLException;
 import  java.sql.Connection;
 import  oracle.jdbc.OracleTypes;
 import  oracle.sql.ORAData;
 import  oracle.sql.ORADataFactory;
 import  oracle.sql.Datum;
 import  oracle.sql.STRUCT;
 import  oracle.jpub.runtime.MutableStruct;

 public   class  testobj  implements  ORAData, ORADataFactory
{
   public   static   final  String _SQL_NAME = "TESTOBJ";
   public   static   final   int  _SQL_TYPECODE = OracleTypes.STRUCT;

   protected  MutableStruct _struct;

   private   static   int [] _sqlType =  {  2 , 12  };
   private   static  ORADataFactory[] _factory =  new  ORADataFactory[ 2 ];
 protected   static   final  testobj _testobjFactory =  new  testobj(false);

   public   static  ORADataFactory getORADataFactory()
  {  return  _testobjFactory; }
  /* constructor */
   protected  testobj( boolean  init)
  {  if (init) _struct =  new  MutableStruct( new  Object[ 2 ], _sqlType, _factory); }
   public  testobj()
  {  this (true); }
   public  testobj(oracle.sql.NUMBER id, oracle.sql. CHAR  value)  throws  SQLException
  {  this (true);
    setId(id);
    setValue(value);
  }

  /* ORAData interface */
   public  Datum toDatum(Connection c)  throws  SQLException
  {
     return  _struct.toDatum(c, _SQL_NAME);
  }


  /* ORADataFactory interface */
   public  ORAData create(Datum d,  int  sqlType)  throws  SQLException
  {  return  create( null , d, sqlType); }
   protected  ORAData create(testobj o, Datum d,  int  sqlType)  throws  SQLException
  {
     if  (d ==  null )  return   null ; 
     if  (o ==  null ) o =  new  testobj(false);
    o._struct =  new  MutableStruct((STRUCT) d, _sqlType, _factory);
     return  o;
  }
  /* accessor methods */
   public  oracle.sql.NUMBER getId()  throws  SQLException
  {  return  (oracle.sql.NUMBER) _struct.getOracleAttribute( 0 ); }

   public   void  setId(oracle.sql.NUMBER id)  throws  SQLException
  { _struct.setOracleAttribute( 0 , id); }


   public  oracle.sql. CHAR  getValue()  throws  SQLException
  {  return  (oracle.sql. CHAR ) _struct.getOracleAttribute( 1 ); }

   public   void  setValue(oracle.sql. CHAR  value)  throws  SQLException
  { _struct.setOracleAttribute( 1 , value); }

}


Код: 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.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
// для коллекции testobjs
 package  pack_new;

 import  java.sql.SQLException;
 import  java.sql.Connection;
 import  oracle.jdbc.OracleTypes;
 import  oracle.sql.ORAData;
 import  oracle.sql.ORADataFactory;
 import  oracle.sql.Datum;
 import  oracle.sql.ARRAY;
 import  oracle.sql.ArrayDescriptor;
 import  oracle.jpub.runtime.MutableArray;

 public   class  testobjs  implements  ORAData, ORADataFactory
{
   public   static   final  String _SQL_NAME = "TESTOBJS";
   public   static   final   int  _SQL_TYPECODE = OracleTypes.ARRAY;

  MutableArray _array;

 private   static   final  testobjs _testobjsFactory =  new  testobjs();

   public   static  ORADataFactory getORADataFactory()
  {  return  _testobjsFactory; }
  /* constructors */
   public  testobjs()
  {
     this ((testobj[]) null );
  }

   public  testobjs(testobj[] a)
  {
    _array =  new  MutableArray( 2002 , a, testobj.getORADataFactory());
  }

  /* ORAData interface */
   public  Datum toDatum(Connection c)  throws  SQLException
  {
     return  _array.toDatum(c, _SQL_NAME);
  }

  /* ORADataFactory interface */
   public  ORAData create(Datum d,  int  sqlType)  throws  SQLException
  {
     if  (d ==  null )  return   null ;
    testobjs a =  new  testobjs();
    a._array =  new  MutableArray( 2002 , (ARRAY) d, testobj.getORADataFactory());
     return  a;
  }

   public   int  length()  throws  SQLException
  {
     return  _array.length();
  }

   public   int  getBaseType()  throws  SQLException
  {
     return  _array.getBaseType();
  }

   public  String getBaseTypeName()  throws  SQLException
  {
     return  _array.getBaseTypeName();
  }

   public  ArrayDescriptor getDescriptor()  throws  SQLException
  {
     return  _array.getDescriptor();
  }

  /* array accessor methods */
   public  testobj[] getArray()  throws  SQLException
  {
     return  (testobj[]) _array.getObjectArray(
       new  testobj[_array.length()]);
  }

   public   void  setArray(testobj[] a)  throws  SQLException
  {
    _array.setObjectArray(a);
  }

   public  testobj[] getArray( long  index,  int  count)  throws  SQLException
  {
     return  (testobj[]) _array.getObjectArray(index,
       new  testobj[_array.sliceLength(index, count)]);
  }

   public   void  setArray(testobj[] a,  long  index)  throws  SQLException
  {
    _array.setObjectArray(a, index);
  }

   public  testobj getElement( long  index)  throws  SQLException
  {
     return  (testobj) _array.getObjectElement(index);
  }

   public   void  setElement(testobj a,  long  index)  throws  SQLException
  {
    _array.setObjectElement(a, index);
  }

}


Теперь пишу основной код хранимой процедуры для возврата коллекции при
вызове из PL/SQL

Код: 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.
// основной код
 package  pack_new;

 import  oracle.sql.CharacterSet;
 import  java.sql.SQLException;

 public   class  stored
{
      public   static   void  call(testobjs[] objs)
     {
         // засекаем время исполнения 
          long  tm = System.currentTimeMillis();

         // подготавливаем массив объектов 	 
         testobj[] obj =  new  testobj[ 50000 ];
         CharacterSet chs = CharacterSet.make(CharacterSet.AL16UTF16_CHARSET);

          try 
         {
             // заполняем коллекцию
              for  ( int  i =  0 ; i <  50000 ; i++)
             {
                 oracle.sql.NUMBER id =  new  oracle.sql.NUMBER(i);
                 oracle.sql. CHAR  value =  new  oracle.sql. CHAR ("text_" + i, chs);

                 obj[i] =  new  testobj(id, value);
             }

             // если ссылка пришла нулевая/ненулевая
              if  (objs[ 0 ] ==  null )
                objs[ 0 ] =  new  testobjs(obj);
              else 
                objs[ 0 ].setArray(obj);
         }
          catch  (SQLException e)
         {
             e.printStackTrace();  
         }

         // время выполнения в USER TRACE
         System.out.println(( double ) (System.currentTimeMillis() - tm)/ 1000 );
     }
}

Компилирую и загружаю пакет loadjava-утилитой и создаю оболочку вызова

Код: plaintext
1.
2.
3.
-- создаю класс-оболочку для вызова
create or replace procedure TestJava(p_objs out nocopy testobjs)
as language java name 'pack_new.stored.call(pack_new.testobjs[])';

Тестирую вызов

Код: plaintext
1.
2.
3.
4.
5.
6.
-- тест JAVA
declare
  p_objs TestObjs;
begin
  TestJava(p_objs); 
end;

Общее время выполнения варьируется от 5 до 10 секунд (ну пусть даже 5).
Формирую коллекцию в PL/SQL

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
-- тест PL/SQL
declare
  p_objs TestObjs := TestObjs();
begin
   for  i in  1 .. 50000  loop
    p_objs.extend;
    p_objs(i) := TestObj(i, 'Text' || i);
  end loop;
end;

Общее время выполнения 0.188 секунды.

Смотрю USER TRACE FILE в Oracle. Время формирования заняло 1.5 секунды
(что тоже не мало, хотелось бы 0.188). Остальное время (5 - 1.5 = 3.5)
заняли непонятные преобразования при возврате данных. Хотя в документации
JDBC for Oracle утверждается, что самую лучшую производительность дают
интерфейсы ORAData, ORADataFactory и использование типов oracle.sql.XXXXX,
которые не требуют внутренних преобразований. Я не знаю JAVA (это мой
первый опыт тесной работы с ней), может кто подскажет в чем проблема и
предложит решение. Производительность мне нужна близкая к той, что показывает
код на PL/SQL (~ 0.188).
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / JAVA & Oracle collections / 1 сообщений из 1, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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