Как и многие старые базы данных, Oracle имеет устаревшие типы данных, с которыми довольно сложно работать в повседневной SQL. Обычно вы больше не сталкиваетесь с типами данных LONG и LONG RAW , но когда вы работаете со старой базой данных или представлениями словаря, вам, возможно, придется иметь дело с LONG .
Эти типы данных в значительной степени совпадают с «более новыми» представлениями больших объектов:
-
LONGиCLOB— это несколько одно и то же, за исключением того, что -
LONG RAWиBLOB— это одно и то же, за исключением того, что
Чтение LONG или LONG RAW из JDBC вызывает исключение «Поток уже закрыт»
Когда у вас есть следующая схема:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
CREATE TABLE t_long_raw_and_blob ( id NUMBER(7), blob1 BLOB, longx LONG RAW, blob2 BLOB, CONSTRAINT pk_t_long_raw_and_blob PRIMARY KEY (id));CREATE TABLE t_long_and_clob ( id NUMBER(7), clob1 CLOB, longx LONG, clob2 CLOB, CONSTRAINT pk_t_long_and_clob PRIMARY KEY (id)); |
… Вы не можете просто выбрать все столбцы из JDBC (или других API) следующим образом:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
try (PreparedStatement s = con.prepareStatement( "SELECT * FROM t_long_raw_and_blob"); ResultSet rs = s.executeQuery()) { while (rs.next()) { System.out.println(); System.out.println("ID = " + rs.getInt(1)); System.out.println("BLOB1 = " + rs.getBytes(2)); System.out.println("LONGX = " + rs.getBytes(3)); System.out.println("BLOB2 = " + rs.getBytes(4)); }} |
Если вы делаете выше, вы столкнетесь с чем-то вроде:
|
1
2
3
4
|
Caused by: java.sql.SQLException: Stream has already been closed at oracle.jdbc.driver.LongRawAccessor.getBytes(LongRawAccessor.java:162) at oracle.jdbc.driver.OracleResultSetImpl.getBytes(OracleResultSetImpl.java:708) ... 33 more |
«Правильным» решением было бы выполнить следующее:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
try (PreparedStatement s = con.prepareStatement( "SELECT * FROM t_long_raw_and_blob"); ResultSet rs = s.executeQuery()) { while (rs.next()) { byte[] longx = rs.getBytes(3); System.out.println(); System.out.println("ID = " + rs.getInt(1)); System.out.println("BLOB1 = " + rs.getBytes(2)); System.out.println("LONGX = " + longx); System.out.println("BLOB2 = " + rs.getBytes(4)); }} |
Вкратце: все столбцы LONG или LONG RAW должны быть получены из ResultSet до всех остальных столбцов.
Это противно
Верно! Какой-то недостаток протокола Oracle низкого уровня просочился за пределы JDBC API, что очень прискорбно. Мы не заботимся об этих деталях. Мы должны иметь возможность получать ресурсы в любом порядке.
В jOOQ мы исправили эту проблему # 4820 , поэтому вы можете запустить свое утверждение и упорядочить столбцы в любом порядке:
|
1
2
3
4
5
6
7
8
9
|
DSL.using(configuration) .select( T_LONG_RAR_AND_BLOB.ID, T_LONG_RAR_AND_BLOB.BLOB1, T_LONG_RAR_AND_BLOB.LONGX, T_LONG_RAR_AND_BLOB.BLOB2 ) .from(T_LONG_RAR_AND_BLOB) .fetch(); |
jOOQ будет внутренне переупорядочивать столбцы при извлечении их из ResultSet , прозрачно.
| Ссылка: | Oracle LONG и LONG RAW Вызывает «Поток уже закрыт» Исключение от нашего партнера JCG Лукаса Эдера в блоге JAVA, SQL и AND JOOQ . |