forked from oracle-samples/oracle-db-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLobBasicSample.java
More file actions
executable file
·691 lines (581 loc) · 22.9 KB
/
LobBasicSample.java
File metadata and controls
executable file
·691 lines (581 loc) · 22.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
/* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.*/
/*
DESCRIPTION
Various lob operations sample.
To run the sample, you must enter the DB user's password from the
console, and optionally specify the DB user and/or connect URL on
the command-line. You can also modify these values in this file
and recompile the code.
java LobBasicSample -l <url> -u <user>
NOTES
Sample uses books.txt and books.png from current directory.
*/
import java.sql.Connection;
import java.sql.NClob;
import java.sql.Statement;
import java.sql.Types;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Blob;
import java.sql.Clob;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.text.NumberFormat;
import oracle.jdbc.internal.OracleStatement;
import oracle.jdbc.pool.OracleDataSource;
import oracle.sql.CLOB;
/**
*
* Shows dealing with the various LOB data types. Shows how to add a row to a
* table that has a LOB column. Shows the LOB 2 LONG code path with
* defineColumnType, LOB prefetch (tune the size). Shows how to create a temp
* lob.
*
* @author igarish
*
*/
public class LobBasicSample {
final static String DEFAULT_URL = "jdbc:oracle:thin:@//myhost:myport/myservice";
final static String DEFAULT_USER = "myuser";
final static String DEFAULT_PASSWORD = "mypassword";
// You must provide non-default values for ALL 3 to execute the program
static String url = DEFAULT_URL;
static String user = DEFAULT_USER;
static String password = DEFAULT_PASSWORD;
// Table name used in this sample
// Sample truncates the table and show lob operations
private final String TABLE_NAME = "LOB_JDBC_SAMPLE";
// Lob read/write chunk buffer size
private final int CHUNK_BUFFER_SIZE = 1024;
// Connection object for various lob operations.
// Sample uses only one connection for all lob
// operations in this demo program.
private Connection conn;
/**
* Entry point of the sample.
*
* @param args
* Command line arguments. Supported command line options: -l <url>
* -u <user>
* @throws Exception
*/
public static void main(String args[]) throws Exception {
LobBasicSample lobBasic = new LobBasicSample();
getRealUserPasswordUrl(args);
// Get connection and initialize schema.
lobBasic.setup();
// Shows clob operations
lobBasic.clobSample();
// Shows clob operations with an empty clob
lobBasic.clobSampleWithEmptyClob();
// Shows blob operations
lobBasic.blobSample();
// Shows blob operations with an empty blob
lobBasic.blobSampleWithEmptyBlob();
// Shows nclob operations
lobBasic.nclobSample();
// Shows temporary clob operations
lobBasic.temporaryClobSample();
// Fetch a CLOB as a LONG
lobBasic.clobAsLongSample();
// Shows how to specify lob prefetch size to fine tune
// clob performance.
lobBasic.clobSampleWithLobPrefetchSize();
// Drop table and disconnect from the database.
lobBasic.cleanup();
}
// Gets connection to the database and truncate the table
void setup() throws SQLException {
conn = getConnection();
truncateTable();
conn.setAutoCommit(false);
}
// Truncates the table and disconnect from the database
void cleanup() throws SQLException {
if (conn != null) {
truncateTable();
conn.close();
conn = null;
}
}
// Shows how to create a Clob, insert data in the Clob,
// retrieves data from the Clob.
void clobSample() throws Exception {
show("======== Clob Sample ========");
try (PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO " + TABLE_NAME + " (LOB_ID, CLOB_DATA) VALUES (1, ?)")) {
// Creates and fill data in the clob
Clob clob = conn.createClob();
clob.setString(1, "Book Title - Java for Dummies");
// Insert clob data in the column of a table.
pstmt.setClob(1, clob);
pstmt.execute();
conn.commit();
// Get data from the clob column.
executeClobQuery(1);
}
}
// Shows how to create an empty Clob, insert data in the Clob,
// retrieves data from the Clob.
void clobSampleWithEmptyClob() throws Exception {
show("======== Clob Sample with an empty clob ========");
// Creates an empty clob in a table then update it with actual data.
try (PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO " + TABLE_NAME + " (LOB_ID, CLOB_DATA) VALUES (2, empty_clob())")) {
pstmt.execute();
try (ResultSet rset = pstmt.executeQuery(
"SELECT CLOB_DATA FROM " + TABLE_NAME + " WHERE LOB_ID=2 FOR UPDATE")) {
while (rset.next()) {
Clob c = rset.getClob(1);
// Fill clob data from a file and update it in the table.
readFileAndUpdateClobData(c, "books.txt");
}
}
conn.commit();
// Get data from the clob column
executeClobQuery(2);
}
}
// Shows how to insert binary stream data in the Blob,
// retrieves data from the Blob.
void blobSample() throws Exception {
show("======== Blob Sample ========");
try (PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO " + TABLE_NAME + " (LOB_ID, BLOB_DATA) VALUES (3, ?)")) {
byte[] data = { 1, 2, 3, 77, 80, 4, 5 };
// Insert binary input stream data in the Blob
pstmt.setBlob(1, new ByteArrayInputStream(data));
pstmt.execute();
conn.commit();
// Get data from the blob column.
executeBlobQuery(3);
}
}
// Shows how to create an empty Blob, insert data in the Blob,
// retrieves data from the Blob.
void blobSampleWithEmptyBlob() throws Exception {
show("======== Blob Sample with an empty blob ========");
// Creates an empty blob in a table then update it with actual data.
try (PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO " + TABLE_NAME + " (LOB_ID, BLOB_DATA) VALUES (4, empty_blob())")) {
pstmt.execute();
try (ResultSet rset = pstmt.executeQuery(
"SELECT BLOB_DATA FROM " + TABLE_NAME + " WHERE LOB_ID=4 FOR UPDATE")) {
while (rset.next()) {
Blob b = rset.getBlob(1);
// Fill blob data from a file and update it in the table.
readFileAndUpdateBlobData(b, "books.png");
}
}
conn.commit();
// Get data from the blob column
executeBlobQuery(4);
}
}
// Shows how to create a NClob, insert data in the NClob,
// retrieves data from the NClob.
void nclobSample() throws Exception {
show("======== Nclob Sample ========");
try (PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO " + TABLE_NAME + " (LOB_ID, NCLOB_DATA) VALUES (5, ?)")) {
// Creates and fill data in the nclob
NClob nclob = conn.createNClob();
nclob.setString(1, "Book Title - Oracle \u00A9 for Dummies ");
// Insert nclob data in the column of a table.
pstmt.setNClob(1, nclob);
pstmt.execute();
conn.commit();
// Get data from the nclob column.
executeNClobQuery(5);
}
}
// You can use temporary LOBs to store transient data. The data is stored in
// temporary
// table space rather than regular table space. You should free temporary LOBs
// after you
// no longer need them. If you do not, then the space the LOB consumes in
// temporary
// table space will not be reclaimed.
//
// Shows how to create a temporary CLOB, fill data in the temporary CLOB,
// insert temporary CLOB data in the table.
void temporaryClobSample() throws Exception {
show("======== Temporary Clob Sample ========");
try (PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO " + TABLE_NAME + " (LOB_ID, CLOB_DATA) VALUES (6, ?)")) {
// Creates and fill data in a temporary clob
Clob tempClob = CLOB.createTemporary(conn, false, CLOB.DURATION_SESSION);
tempClob.setString(1, "Book Title - JDBC for Dummies");
// Insert temporary CLOB data in the column of a table.
pstmt.setClob(1, tempClob);
pstmt.execute();
conn.commit();
// Check whether the CLOB is temporary or regular CLOB.
boolean isTempCLOB = CLOB.isTemporary((CLOB) tempClob);
show("CLOB.isTemporary: " + isTempCLOB);
// Free temporary CLOB
CLOB.freeTemporary((CLOB) tempClob);
// Get data from the clob column.
executeClobQuery(6);
}
}
// Fetch a CLOB as a LONG
void clobAsLongSample() throws Exception {
show("======== Clob as Long Sample ========");
try (PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO " + TABLE_NAME + " (LOB_ID, CLOB_DATA) VALUES (7, ?)")) {
// Creates and fill data in the clob
Clob clob = conn.createClob();
clob.setString(1, "Book Title - JNI for Dummies");
// Insert clob data in the column of a table.
pstmt.setClob(1, clob);
pstmt.execute();
conn.commit();
// Get data from the clob column as if it's LONG type.
executeClobAsLongQuery(7);
}
}
// Shows how to set lob prefetch size,
// while retrieving clob data to reduce round trips to the server.
void clobSampleWithLobPrefetchSize() throws Exception {
show("======== Clob Sample with LobPrefetchSize ========");
try (PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO " + TABLE_NAME + " (LOB_ID, CLOB_DATA) VALUES (8, ?)")) {
// Creates and fill data in the clob
Clob clob = conn.createClob();
clob.setString(1, "Book Title - Linux for Dummies");
// Insert clob data in the column of a table.
pstmt.setClob(1, clob);
pstmt.execute();
conn.commit();
// Sets lob preftech size and gets data from the clob column
executeClobQueryWithLobPrefetchSize(8);
}
}
// Execute a query to get the clob column data.
// Iterate through the result.
private void executeClobQuery(int id) throws Exception {
try (PreparedStatement pstmt = conn
.prepareStatement("SELECT CLOB_DATA FROM " + TABLE_NAME + " WHERE LOB_ID=?")) {
pstmt.setInt(1, id);
try (ResultSet rset = pstmt.executeQuery()) {
show("LOB_ID = " + id);
while (rset.next()) {
Clob c = rset.getClob(1);
getAndDisplayClobData("CLOB_DATA = ", c);
}
}
}
}
// Get the clob data as a stream.
private void getAndDisplayClobData(String message, Clob clob)
throws Exception {
// Get a character stream of a clob
try (Reader clobStream = clob.getCharacterStream()) {
// Buffer to read chunk of data
char[] buffer = new char[CHUNK_BUFFER_SIZE];
int length = 0;
showln(message);
// Loop for the reading of clob data in chunks.
while ((length = clobStream.read(buffer)) != -1)
showln(new String(buffer, 0, length));
show("");
}
}
// Read data from a text file and insert it in to the clob column
private void readFileAndUpdateClobData(Clob clob, String fileName)
throws Exception {
// File reader
File file = new File(fileName);
try (FileInputStream fileInputStream = new FileInputStream(file)) {
try (InputStreamReader inputStreamReader = new InputStreamReader(
fileInputStream)) {
try (BufferedReader bufferedReader = new BufferedReader(
inputStreamReader)) {
// Buffer to read/write chunk of data
char[] buffer = new char[CHUNK_BUFFER_SIZE];
int charsRead = 0;
// Get a clob writer
try (Writer writer = clob.setCharacterStream(1L)) {
// Loop for reading of chunk of data and then write into the clob.
while ((charsRead = bufferedReader.read(buffer)) != -1) {
writer.write(buffer, 0, charsRead);
}
}
}
}
}
}
// Execute a query to get the blob column data.
// Iterate through the result.
private void executeBlobQuery(int id) throws Exception {
try (PreparedStatement pstmt = conn
.prepareStatement("SELECT BLOB_DATA FROM " + TABLE_NAME + " WHERE LOB_ID=?")) {
pstmt.setInt(1, id);
try (ResultSet rset = pstmt.executeQuery()) {
show("LOB_ID = " + id);
while (rset.next()) {
Blob b = rset.getBlob(1);
getAndDisplayBlobData("BLOB_DATA = ", b);
}
}
}
}
// Get the blob data as a stream.
private void getAndDisplayBlobData(String message, Blob blob)
throws Exception {
// Get a binary stream of a blob
try (InputStream blobStream = blob.getBinaryStream()) {
// Buffer to read chunk of data
byte[] buffer = new byte[CHUNK_BUFFER_SIZE];
int length = 0;
long totalLength = 0;
NumberFormat format = NumberFormat.getInstance();
format.setMinimumIntegerDigits(2);
format.setGroupingUsed(false);
// Loop for the reading of blob data in chunks.
while ((length = blobStream.read(buffer)) != -1) {
if (totalLength == 0 && length > 25)
show("First 25 bytes of a Blob column");
for (int i = 0; i < length; i++) {
int b = (int) buffer[i] & 0XFF;
if (totalLength == 0 && i < 25)
showln(format.format((long) b) + " ");
else
break; // We are not consuming more than 25 bytes for demo purpose.
}
totalLength += length;
}
show("");
if (totalLength > 25)
show("Total blob data length:" + totalLength);
}
}
// Read data from a binary file and insert it in to the blob column
private void readFileAndUpdateBlobData(Blob blob, String fileName)
throws Exception {
// File reader
File file = new File(fileName);
try (FileInputStream fileInputStream = new FileInputStream(file)) {
// Buffer to read/write chunk of data
byte[] buffer = new byte[CHUNK_BUFFER_SIZE];
int bytesRead = 0;
// Get a blob output stream
try (OutputStream outstream = blob.setBinaryStream(1L)) {
// Loop for reading of chunk of data and then write into the blob.
while ((bytesRead = fileInputStream.read(buffer)) != -1) {
outstream.write(buffer, 0, bytesRead);
}
}
}
}
// Execute a query to get the nclob column data.
// Iterate through the result.
private void executeNClobQuery(int id) throws Exception {
try (PreparedStatement pstmt = conn
.prepareStatement("SELECT NCLOB_DATA FROM " + TABLE_NAME + " WHERE LOB_ID=?")) {
pstmt.setInt(1, id);
try (ResultSet rset = pstmt.executeQuery()) {
show("LOB_ID = " + id);
while (rset.next()) {
NClob n = rset.getNClob(1);
getAndDisplayNClobData("NCLOB_DATA = ", n);
}
}
}
}
// Get the nclob data as a stream.
private void getAndDisplayNClobData(String message, NClob nclob)
throws Exception {
// Get a character stream of a nclob
try (Reader nclobStream = nclob.getCharacterStream()) {
// Buffer to read chunk of data
char[] buffer = new char[CHUNK_BUFFER_SIZE];
int length = 0;
showln(message);
// Loop for the reading of nclob data in chunks.
while ((length = nclobStream.read(buffer)) != -1)
showln(new String(buffer, 0, length));
show("");
}
}
// Execute a query to get the clob column data.
// Iterate through the result as LONG type.
private void executeClobAsLongQuery(int id) throws Exception {
try (PreparedStatement pstmt = conn
.prepareStatement("SELECT CLOB_DATA FROM " + TABLE_NAME + " WHERE LOB_ID=?")) {
// Fetch LOB data as LONG.
// LOB data can be read using the same streaming mechanism as for LONG RAW
// and LONG data.
// This produces a direct stream on the data as if it were a LONG RAW or
// LONG column.
// This technique is limited to Oracle Database 10g release 1 (10.1) and
// later.
// The benefit of fetching a CLOB as a LONG (or a BLOB as a LONG_RAW) is
// that the data
// will be inlined in the data row that is fetched which may become handy
// when the locator
// is not needed and you just need to read the data into a stream.
// The downside of it is that you don't get the locator and the rows are
// fetched one by one.
// The LOB prefetch gives better benefits such as being able to fetch
// multiple rows in one single roundtrip,
// getting the length of the LOB immediately and getting the locator.
// Overall relying on LOB prefetch is always preferable compared to the
// LOB to LONG technique.
((OracleStatement) pstmt).defineColumnType(2, Types.LONGVARBINARY);
pstmt.setInt(1, id);
try (ResultSet rset = pstmt.executeQuery()) {
show("LOB_ID = " + id);
while (rset.next()) {
String c = rset.getString(1);
show("CLOB_DATA as LONG = " + c);
}
}
}
}
// If you select LOB columns into a result set, some or all of the data is
// prefetched to the client, when the locator is fetched. It saves the first
// roundtrip to
// retrieve data by deferring all preceding operations until fetching from the
// locator.
//
// The prefetch size is specified in bytes for BLOBs and in characters for
// CLOBs. It can be
// specified by setting the connection property
// oracle.jdbc.defaultLobPrefetchSize.
// The value of this property can be overridden at statement level by using,
// oracle.jdbc.OracleStatement.setLobPrefetchSize(int) method.
//
// The default prefetch size is 4000.
//
// Execute a query to get the clob column data.
// Iterate through the result.
private void executeClobQueryWithLobPrefetchSize(int id) throws Exception {
try (PreparedStatement pstmt = conn
.prepareStatement("SELECT CLOB_DATA FROM " + TABLE_NAME + " WHERE LOB_ID=?")) {
// Fine tune lob prefetch size to reduce number of round trips.
((OracleStatement) pstmt).setLobPrefetchSize(5000);
pstmt.setInt(1, id);
try (ResultSet rset = pstmt.executeQuery()) {
show("LOB_ID = " + id);
while (rset.next()) {
Clob c = rset.getClob(1);
getAndDisplayClobData("CLOB_DATA = ", c);
}
}
}
}
// ==============================Utility Methods==============================
private void truncateTable() throws SQLException {
try (Statement stmt = conn.createStatement()) {
String sql = "TRUNCATE TABLE " + TABLE_NAME;
stmt.execute(sql);
}
}
private Connection getConnection() throws SQLException {
// Create an OracleDataSource instance and set properties
OracleDataSource ods = new OracleDataSource();
ods.setUser(user);
ods.setPassword(password);
ods.setURL(url);
return ods.getConnection();
}
static void getRealUserPasswordUrl(String args[]) throws Exception {
// URL can be modified in file, or taken from command-line
url = getOptionValue(args, "-l", DEFAULT_URL);
// DB user can be modified in file, or taken from command-line
user = getOptionValue(args, "-u", DEFAULT_USER);
// DB user's password can be modified in file, or explicitly entered
readPassword(" Password for " + user + ": ");
}
// Get specified option value from command-line, or use default value
static String getOptionValue(String args[], String optionName,
String defaultVal) {
String argValue = "";
try {
int i = 0;
String arg = "";
boolean found = false;
while (i < args.length) {
arg = args[i++];
if (arg.equals(optionName)) {
if (i < args.length)
argValue = args[i++];
if (argValue.startsWith("-") || argValue.equals("")) {
argValue = defaultVal;
}
found = true;
}
}
if (!found) {
argValue = defaultVal;
}
} catch (Exception e) {
showError("getOptionValue", e);
}
return argValue;
}
static void readPassword(String prompt) throws Exception {
if (System.console() == null) {
BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
showln(prompt);
password = r.readLine();
} else {
char[] pchars = System.console().readPassword("\n[%s]", prompt);
if (pchars != null) {
password = new String(pchars);
java.util.Arrays.fill(pchars, ' ');
}
}
}
private static void show(String msg) {
System.out.println(msg);
}
// Show message line without new line
private static void showln(String msg) {
System.out.print(msg);
}
static void showError(String msg, Throwable exc) {
System.out.println(msg + " hit error: " + exc.getMessage());
}
}
/*
* ==================================== Expected Output
* ====================================
*
* ======== Clob Sample ======== LOB_ID = 1 CLOB_DATA = Book Title - Java for Dummies
* ======== Clob Sample with an empty clob ======== LOB_ID = 2 CLOB_DATA = { "books": [ {
* "isbn": "9781593275846", "title": "Eloquent JavaScript, Second Edition",
* "subtitle": "A Modern Introduction to Programming", "author":
* "Marijn Haverbeke", "published": "2014-12-14T00:00:00.000Z", "publisher":
* "No Starch Press", "pages": 472, "description":
* "JavaScript lies at the heart of almost every modern web application, from social apps to the newest browser-based games. Though simple for beginners to pick up and play with, JavaScript is a flexible, complex language that you can use to build full-scale applications."
* , "website": "http://eloquentjavascript.net/" }, { "isbn": "9781449331818",
* "title": "Learning JavaScript Design Patterns", "subtitle":
* "A JavaScript and jQuery Developer's Guide", "author": "Addy Osmani",
* "published": "2012-07-01T00:00:00.000Z", "publisher": "O'Reilly Media",
* "pages": 254, "description":
* "With Learning JavaScript Design Patterns, you'll learn how to write beautiful, structured, and maintainable JavaScript by applying classical and modern design patterns to the language. If you want to keep your code efficient, more manageable, and up-to-date with the latest best practices, this book is for you."
* , "website":
* "http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/" } ] }
*
* ======== Blob Sample ======== LOB_ID = 3 01 02 03 77 80 04 05 ======== Blob
* Sample with an empty blob ======== LOB_ID = 4 First 25 bytes of a Blob column 137
* 80 78 71 13 10 26 10 00 00 00 13 73 72 68 82 00 00 00 200 00 00 00 198 08
* Total blob data length:10422 ======== Nclob Sample ======== LOB_ID = 5 NCLOB_DATA = Book
* Title - Oracle ? for Dummies ======== Temporary Clob Sample ========
* CLOB.isTemporary: true LOB_ID = 6 CLOB_DATA = Book Title - JDBC for Dummies ======== Clob
* as Long Sample ======== LOB_ID = 7 CLOB_DATA as LONG = Book Title - JNI for Dummies
* ======== Clob Sample with LobPrefetchSize ======== LOB_ID = 8 CLOB_DATA = Book Title -
* Linux for Dummies
*
*/