Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Oracle > черти чего в JDBC (Оракл)


Автор: Sleepy_PIP 30.10.2005, 18:55
короче вот так:
Код

ResultSet rr = selDS.executeQuery();
....
                        byte bb[]= rr.getBytes(i);                        
                        oracle.sql.BLOB b=new oracle.sql.BLOB(cc.connORA,bb); 
                        b.setBytes(bb);
                        
                        insS.setBLOB(i, b);
....



где:
ResultSet rr,
OraclePreparedStatement insS=(OraclePreparedStatement)cc.connORA.prepareStatement(insSQL);
на insS.executeQuery()
получаем ошибку:
java.sql.SQLException: ORA-24813: нельзя отправить или получить неподдерживаемый LOB
при попытке записать боолее 4000 байт. (а может и не в этом дело??)
Граница - общеизвестная, да.
объявление таблицы в интересующем поле:
Код
CREATE TABLE inventory
    (suid                           VARCHAR2(30) NOT NULL,
.....
    xmlbody                        BLOB,
...
)
  PCTFREE     10
  INITRANS    1
  MAXTRANS    255
  TABLESPACE  jtrump_main_data
  STORAGE   (
    INITIAL     65536
    MINEXTENTS  1
    MAXEXTENTS  2147483645
  )
....
  LOB (XMLBODY) STORE AS
  (
  TABLESPACE  jtrump_main_lob
  STORAGE   (
    INITIAL     65536
    MINEXTENTS  1
    MAXEXTENTS  2147483645
  )
   NOCACHE LOGGING
   CHUNK 8192
   PCTVERSION 10
  )
...
/


-- Indexes for INVENTORY

CREATE INDEX inventory_title_translit ON inventory
  (
    UPPER("TITLE_TRANSLIT") ASC
  )
  PCTFREE     5
  INITRANS    2
  MAXTRANS    255
  TABLESPACE  jtrump_main_idx
  STORAGE   (
    INITIAL     106496
    MINEXTENTS  1
    MAXEXTENTS  2147483645
  )
/
CREATE INDEX inventory_title_translit_cs ON inventory
  (
    title_translit                  ASC
  )
  PCTFREE     5
  INITRANS    2
  MAXTRANS    255
  TABLESPACE  jtrump_main_idx
  STORAGE   (
    INITIAL     106496
    MINEXTENTS  1
    MAXEXTENTS  2147483645
  )
/
CREATE INDEX inventory_translit_upper ON inventory
  (
    title_translit_upper            ASC
  )
  PCTFREE     5
  INITRANS    2
  MAXTRANS    255
  TABLESPACE  jtrump_main_idx
  STORAGE   (
    INITIAL     106496
    MINEXTENTS  1
    MAXEXTENTS  2147483645
  )
/

уже понимаю что есть ограничения в 4к, что храняться в основной таблице. как это обойти?



Автор: LSD 30.10.2005, 19:18
Где выполняется данный код, внутри сервера Oracle или на клиенте?
Когда код выполняется внутри сервера Oracle используется другой JDBC драйвер, который не позволяет получать blob в виде byte[] если он по размеру больше 4К. Приходилось использовать Blob.getBinaryStream().

P.S. В доке также написанно, что данная ошибка может возникать если используются разные версии сервера и клиента, ты проверял версии совпадают?

Автор: Sleepy_PIP 30.10.2005, 19:33
Цитата(LSD @ 30.10.2005, 19:18)
Где выполняется данный код, внутри сервера Oracle или на клиенте?
Когда код выполняется внутри сервера Oracle используется другой JDBC драйвер, который не позволяет получать blob в виде byte[] если он по размеру больше 4К. Приходилось использовать Blob.getBinaryStream().

P.S. В доке также написанно, что данная ошибка может возникать если используются разные версии сервера и клиента, ты проверял версии совпадают?

на клиенте. счаз попробую через стиримы. хотя ошибка говорит о не соместимости клинта и сервера. однако клиент от 9.1.2 и сервер тот-же. ...

Автор: LSD 30.10.2005, 23:39
Цитата(Sleepy_PIP @ 30.10.2005, 20:33)
хотя ошибка говорит о не соместимости клинта и сервера

Цитата
ORA-24813: cannot send or receive an unsupported LOB
Cause: An attempt was made to send a LOB across the network, but either the server does not support the LOB sent by the client, or the client does not support the LOB sent by the server. This error usually occurs when the client and server are running different versions of Oracle.
Action: Use a version of the Oracle that supports the LOB on both the client and the server.

Автор: Sleepy_PIP 31.10.2005, 04:48
Цитата(LSD @ 30.10.2005, 23:39)
Цитата(Sleepy_PIP @ 30.10.2005, )
хотя ошибка говорит о не соместимости клинта и сервера

Цитата
ORA-24813: cannot send or receive an unsupported LOB
Cause: An attempt was made to send a LOB across the network, but either the server does not support the LOB sent by the client, or the client does not support the LOB sent by the server. This error usually occurs when the client and server are running different versions of Oracle.
Action: Use a version of the Oracle that supports the LOB on both the client and the server.

сделал так:
Код

                        InputStream is=rr.getBinaryStream(i);
                        if((is.available()<0)||(is.available()==0))
                        {
                            insS.setNull(i, java.sql.Types.BLOB);
                        }
                        else
                        {
                            insS.setBinaryStream(i, is, is.available());
                        }



ошибки не возникает, но ничего в блоб не пишется (а данные - есть - во входном ResultSet'е rr).

А как проверить версию клиента?
У меня все стоит локально - и прогрмака и сервер на одной машинке.
Сервер у меня 9.2.0.1.0 .
отдельно никакого клиента не ставил, но ранее тут-же стоял Oracle8i, так что возможно клиент и не тот.
Как проверить какой клиент актуален?

и еще:
сейсчаз я пытаюсь работать с полями типа BLOB, а ранее работал с полем LONG RAW таким куском кода:
Код

...
byte bb[];
...
bb=my_string.getBytes();

                    insDSb.setBytes(2, bb);


и все было прекрасно. но теперь мне нужны _именно_ blob ...

Спасибо!

PS: да, я делаю вставку - т.е. insS - это инсертный стейтмент

Автор: Sleepy_PIP 31.10.2005, 05:34
YES!!! заработало вот как:
Код

....
                        byte bb[]= rr.getBytes(i);
                        BLOB blob = BLOB.createTemporary(cc.connORA,true,BLOB.DURATION_CALL);
                        blob.putBytes(i,bb);
                        insS.setBLOB(i, blob);



теперь остается проверить целостность данных smile.
подозреваю что это как-бы так по мягче сказать - не совсем правильный подход smile.
Подскажите как тогда правильно делать, а?

Спасибо!


PS: а с блобом таким временным чего делать еще надо после завершения стейтмента? а то вдруг они в коннекте копятся, а? (в доке не сказано ничего).

Автор: LSD 31.10.2005, 10:52
Цитата(Sleepy_PIP @ 31.10.2005, 06:34)
PS: а с блобом таким временным чего делать еще надо после завершения стейтмента? а то вдруг они в коннекте копятся, а? (в доке не сказано ничего).

По идее он должен освобождаться по окончании вызова, но для надежности можешь его очистить BLOB.freeTemporary().

Автор: Sleepy_PIP 1.11.2005, 11:24
Цитата(LSD @ 31.10.2005, 10:52)
Цитата(Sleepy_PIP @ 31.10.2005, )
PS: а с блобом таким временным чего делать еще надо после завершения стейтмента? а то вдруг они в коннекте копятся, а? (в доке не сказано ничего).

По идее он должен освобождаться по окончании вызова, но для надежности можешь его очистить BLOB.freeTemporary().

Да. экспериментально подтверждена необходимость освобождения БЛОБов после каждого выполнения стейтмента.
Иначе рано или позно переполняется shared pool.

Но все оказалось еще интереснее.
В качестве тестовых данных использовались читабельные строки. (ну разумеется байтовое их представление).
Так вот - при приведенном способе при последующем контрольном чтении после коммита вставки в БЛОБах оказывалась нужная строка, предваренная 44 символами 0x20 (пробел) с начала.
почем так - не ведаю.

В результате перешел как и советовал LSD на стримовый подход.
теперь правильная вставка (заполение) блоба выглядит так:
Код

                                BLOB blob = BLOB.createTemporary(cc.connORA, true, BLOB.DURATION_CALL);
                                OutputStream os=blob.getBinaryOutputStream();

                                os.write(bb);
                                os.close();

                                insS.setBLOB(i, blob);



контролькое чтение подтверждает что в БД именно то, что заносилось.
Такие вот дела.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)