Oracle LONG and LONG RAW Causing “Stream has already been closed” Exception

Oracle LONG and LONG RAW Causing “Stream has already been closed” Exception

"

In short: All LONG or LONG RAW columns have to be retrieved from the ResultSet prior to all the other columns.

重要的事:rs.getBytes(3) 一定要放在其它的rs.getXXX的前面。(找了两天,才发现是这个问题,记在这让后来者少走弯路

"

Like many old databases, Oracle has legacy data types, which are rather nasty to work with in every day SQL. Usually, you don’t run into wild encounters of LONG and LONG RAW data types anymore, but when you’re working with an old database, or with the dictionary views, you might just have to deal with LONG.

These data types are pretty much the same thing as the “newer” LOB representations:

  • LONG and CLOB are somewhat the same thing, except they aren’t
  • LONG RAW and BLOB are somewhat the same thing, except they aren’t

Reading LONG or LONG RAW from JDBC causes a “Stream has already been closed” exception

When you have the following schema:

1

2

3

4

5

6

7

8

9

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)

);

… you cannot just simply select all columns from JDBC (or other APIs) like this:

1

2

3

4

5

6

7

8

9

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));

    }

}

If you’re doing the above, you’ll run into something along the lines of:

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

The “correct” solution would be, to run the following, instead:

1

2

3

4

5

6

7

8

9

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));

    }

}

In short: All LONG or LONG RAW columns have to be retrieved from the ResultSet prior to all the other columns.

重要的事:rs.getBytes(3) 一定要放在其它的rs.getXXX的前面。(找了两天,才发现是这个问题,记在这让后来者少走弯路

https://blog.jooq.org/2015/12/30/oracle-long-and-long-raw-causing-stream-has-already-been-closed-exception/

转载于:https://my.oschina.net/jms0755/blog/860910

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值