JDBC for SQL Server - Herong's Tutorial Examples - v3.14, by Herong Yang
Closing InputStream Too Early on setCharacterStream()
This section describes an error condition where executeUpdate() gives an exception if the Reader is closed too early.
The program in the previous tutorial worked nicely. But if you make a mistake by placing the bodyIn.close() statement before ps.executeUpdate(), you will get an IOException when ps.executeUpdate() is called. The reason is simple, reading of data from the Reader is done at the time of executeUpdate() call, not before. Here is a test program:
/* SqlServerClobSetCharacterStreamError.java * Copyright (c) HerongYang.com. All Rights Reserved. */ import java.io.*; import java.sql.*; public class SqlServerClobSetCharacterStreamError { public static void main(String [] args) { Connection con = null; try { com.microsoft.sqlserver.jdbc.SQLServerDataSource ds = new com.microsoft.sqlserver.jdbc.SQLServerDataSource(); ds.setServerName("localhost"); // ds.setPortNumber(60782); ds.setInstanceName("SQLEXPRESS"); ds.setDatabaseName("AdventureWorks2019"); ds.setUser("Herong"); ds.setPassword("T0pSecret"); con = ds.getConnection(); // Deleting the record for re-testing String subject = "Test of setCharacterStream() methods"; Statement sta = con.createStatement(); sta.executeUpdate("DELETE FROM Article WHERE Subject = '" +subject+"'"); // Inserting CLOB value with a PreparedStatement PreparedStatement ps = con.prepareStatement( "INSERT INTO Article (Subject, Body) VALUES (?,?)"); ps.setString(1, subject); Reader bodyIn = new FileReader("SqlServerClobSetCharacterStream.java"); File fileIn = new File("SqlServerClobSetCharacterStream.java"); ps.setCharacterStream(2, bodyIn, (int) fileIn.length()); // Error - Closing the Reader too early. bodyIn.close(); int count = ps.executeUpdate(); ps.close(); // Retrieving CLOB value with getString() sta = con.createStatement(); ResultSet res = sta.executeQuery("SELECT * FROM Article" +" WHERE Subject = '"+subject+"'"); res.next(); System.out.println("The inserted record: "); System.out.println(" Subject = "+res.getString("Subject")); System.out.println(" Body = " +res.getString("Body").substring(0,256)); res.close(); sta.close(); con.close(); } catch (Exception e) { e.printStackTrace(); } } }
The IOException with newer versions of JDK is shown below. The message tells me that the Reader is closed.
herong> java -cp .;mssql-jdbc-9.4.1.jre16.jar \ SqlServerClobSetCharacterStreamError com.microsoft.sqlserver.jdbc.SQLServerException: An error occurred while reading the value from the stream object. Error: "java.io.IOException: Stream closed" at com.microsoft.sqlserver.jdbc.TDSWriter.error(IOBuffer.java:3576) at com.microsoft.sqlserver.jdbc.TDSWriter.writeReader(IOBuffer.ja... at com.microsoft.sqlserver.jdbc.TDSWriter.writeRPCReaderUnicode(I... at com.microsoft.sqlserver.jdbc.DTV$SendByRPCOp.execute(dtv.java:... at com.microsoft.sqlserver.jdbc.DTV.executeOp(dtv.java:1464) at com.microsoft.sqlserver.jdbc.DTV.sendByRPC(dtv.java:1503) ...
However, with JDK 1.6, the error message doesn't tell me that the Reader is closed.
herong> Progra~1\java\jdk1.6.0_02\bin\java \ -cp .;sqljdbc.jar SqlServerClobSetCharacterStreamError com.microsoft.sqlserver.jdbc.SQLServerException: Unexpected IOException processing character stream Reader. at com.microsoft.sqlserver.jdbc.SQLServerException .makeFromDriverError(...) at com.microsoft.sqlserver.jdbc.IOBuffer .bufferAppendRPCReader(...) at com.microsoft.sqlserver.jdbc.DTV$SendByRPCOp.execute(...) at com.microsoft.sqlserver.jdbc.DTV.executeOp(Unknown Source) at com.microsoft.sqlserver.jdbc.DTV.sendByRPC(Unknown Source) at com.microsoft.sqlserver.jdbc.Parameter.sendByRPC(...)
Table of Contents
JDBC (Java Database Connectivity) Introduction
Microsoft SQL Server Express Edition
Microsoft JDBC Driver for SQL Server
Microsoft JDBC Driver - Query Statements and Result Sets
Microsoft JDBC Driver - DatabaseMetaData Object
Microsoft JDBC Driver - DDL Statements
Microsoft JDBC Driver - DML Statements
SQL Server - PreparedStatement
►SQL Server CLOB (Character Large Object) - TEXT
Overview of CLOB (Character Large Object)
Create Tables with CLOB Columns
Inserting CLOB Values with SQL INSERT Statements
Inserting CLOB Values with setString() Method
Inserting CLOB Values with setCharacterStream() Method
►Closing InputStream Too Early on setCharacterStream()
Retrieving CLOB Values with getString() Method
Retrieving CLOB Values with getCharacterStream() Method
Retrieving CLOB Values with getClob() Method
Inserting CLOB Values with setClob() Method
SQL Server BLOB (Binary Large Object) - BLOB
Using Connection Pool with JDBC
JDBC-ODBC Bridge Driver - sun.jdbc.odbc.JdbcOdbcDriver
JDBC-ODBC Bridge Driver - Flat Text Files
JDBC-ODBC Bridge Driver - MS Access