черти чего в JDBC (Оракл)

 
0
 
Oracle
ava
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к, что храняться в основной таблице. как это обойти?


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

P.S. В доке также написанно, что данная ошибка может возникать если используются разные версии сервера и клиента, ты проверял версии совпадают?
ava
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 и сервер тот-же. ...
ava
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.
ava
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 - это инсертный стейтмент
ava
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: а с блобом таким временным чего делать еще надо после завершения стейтмента? а то вдруг они в коннекте копятся, а? (в доке не сказано ничего).
ava
LSD | 31.10.2005, 10:52 #
Цитата (Sleepy_PIP @ 31.10.2005, 06:34)
PS: а с блобом таким временным чего делать еще надо после завершения стейтмента? а то вдруг они в коннекте копятся, а? (в доке не сказано ничего).

По идее он должен освобождаться по окончании вызова, но для надежности можешь его очистить BLOB.freeTemporary().
ava
Sleepy_PIP | 01.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);



контролькое чтение подтверждает что в БД именно то, что заносилось.
Такие вот дела.
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
ava  LSD   Sleepy_PIP
advanced
Submit