Oracle8: I JDBC Developer's Guide and Reference
Oracle8: I JDBC Developer's Guide and Reference
Oracle8: I JDBC Developer's Guide and Reference
Release 8.1.5
February 1999
Part No. A64685-01
Oracle8i JDBC Developer’s Guide and Reference, Release 8.1.5
Contributors: Prabha Krishna, Bernie Harris, Ana Hernandez, Anthony Lau, Paul Lo, Jack Melnick,
Janice Wong, Brian Wright, Joyce Yang
The programs are not intended for use in any nuclear, aviation, mass transit, medical, or other
inherently dangerous applications. It shall be licensee’s responsibility to take all appropriate fail-safe,
back up, redundancy and other measures to ensure the safe use of such applications if the Programs
are used for such purposes, and Oracle disclaims liability for any damages caused by such use of the
Programs.
This Program contains proprietary information of Oracle Corporation; it is provided under a license
agreement containing restrictions on use and disclosure and is also protected by copyright, patent and
other intellectual property law. Reverse engineering of the software is prohibited.
The information contained in this document is subject to change without notice. If you find any problems
in the documentation, please report them to us in writing. Oracle Corporation does not warrant that this
document is error free. No part of this document may be reproduced or transmitted in any form or by
any means, electronic or mechanical, for any purpose, without the express written permission of Oracle
Corporation
If this Program is delivered to a U.S. Government Agency of the Department of Defense, then it is
delivered with Restricted Rights and the following legend is applicable:
Restricted Rights Legend Programs delivered subject to the DOD FAR Supplement are "commercial
computer software" and use, duplication and disclosure of the Programs shall be subject to the licensing
restrictions set forth in the applicable Oracle license agreement. Otherwise, Programs delivered subject to
the Federal Acquisition Regulations are "restricted computer software" and use, duplication and
disclosure of the Programs shall be subject to the restrictions in FAR 52.227-14, Rights in Data -- General,
including Alternate III (June 1987). Oracle Corporation, 500 Oracle Parkway, Redwood City, CA 94065.
Oracle is a registered trademark, and PL/SQL, JDeveloper, Net8, Oracle Objects, Oracle8i, Oracle8, and
other Oracle products mentioned herein are trademarks or registered trademarks of Oracle Corporation.
All other company or product names mentioned are used for identification purposes only and may be
trademarks of their respective owners.
Contents
Preface............................................................................................................................................................ xi
Intended Audience ................................................................................................................................ xi
Manual Structure ................................................................................................................................... xi
Related Documentation ....................................................................................................................... xii
Conventions Used in this Manual ...................................................................................................... xv
1 Overview
What is JDBC? ..................................................................................................................................... 1-2
JDBC versus SQLJ .............................................................................................................................. 1-2
Advantages of SQLJ over JDBC for Static SQL ........................................................................ 1-3
General Guidelines for using JDBC and SQLJ ......................................................................... 1-3
Basic Driver Architecture .................................................................................................................. 1-4
JDBC Thin Client-Side Driver Architecture.............................................................................. 1-5
JDBC OCI Client-Side Driver Architecture............................................................................... 1-5
JDBC Server Driver Architecture ............................................................................................... 1-6
Oracle Extensions to the JDBC Standard ....................................................................................... 1-6
Supported JDK and JDBC Versions................................................................................................ 1-6
JDBC and the Oracle Application Server....................................................................................... 1-6
JDBC and IDEs.................................................................................................................................... 1-7
2 Getting Started
Oracle JDBC Drivers .......................................................................................................................... 2-2
iii
Introducing the Oracle JDBC Drivers ........................................................................................ 2-2
Choosing the Appropriate Driver .............................................................................................. 2-4
Requirements and Compatibilities for Oracle JDBC Drivers.................................................... 2-5
Verifying a JDBC Client Installation .............................................................................................. 2-6
Check Installed Directories and Files......................................................................................... 2-6
Check the Environment Variables.............................................................................................. 2-7
Make Sure You Can Compile and Run Java ............................................................................. 2-7
Determining the Version of the JDBC Driver ........................................................................... 2-8
Testing JDBC and the Database Connection: JdbcCheckup ................................................... 2-8
3 Basic Features
First Steps in JDBC ............................................................................................................................. 3-2
Importing Packages ...................................................................................................................... 3-2
Registering the JDBC Drivers...................................................................................................... 3-3
Opening a Connection to a Database......................................................................................... 3-3
Creating a Statement Object ........................................................................................................ 3-8
Executing a Query and Returning a Result Set Object ............................................................ 3-8
Processing the Result Set ............................................................................................................. 3-9
Closing the Result Set and Statement Objects .......................................................................... 3-9
Closing the Connection.............................................................................................................. 3-10
Sample: Connecting, Querying, and Processing the Results ................................................... 3-10
Datatype Mappings .......................................................................................................................... 3-11
Oracle JDBC Extension Types................................................................................................... 3-12
Using Java Streams in JDBC ........................................................................................................... 3-14
Streaming LONG or LONG RAW Columns........................................................................... 3-14
Streaming CHAR, VARCHAR, or RAW Columns................................................................ 3-19
Data Streaming and Multiple Columns .................................................................................. 3-20
Streaming and Row Prefetching............................................................................................... 3-23
Closing a Stream ......................................................................................................................... 3-23
Streaming LOBs and External Files.......................................................................................... 3-23
Using Stored Procedures in JDBC Programs............................................................................... 3-24
PL/SQL Stored Procedures....................................................................................................... 3-24
Java Stored Procedures .............................................................................................................. 3-25
Error Messages and JDBC ............................................................................................................... 3-25
Server-Side Basics ............................................................................................................................. 3-26
iv
Session and Transaction Context ............................................................................................. 3-26
Connecting to the Database ...................................................................................................... 3-26
Application Basics versus Applet Basics ..................................................................................... 3-27
Application Basics ...................................................................................................................... 3-27
Applet Basics ............................................................................................................................... 3-27
4 Oracle Extensions
Introduction to Oracle Extensions................................................................................................... 4-2
Oracle JDBC Packages and Classes................................................................................................. 4-6
Classes of the oracle.jdbc2 Package ........................................................................................... 4-6
Classes of the oracle.sql Package................................................................................................ 4-7
Classes of the oracle.jdbc.driver Package................................................................................ 4-22
Data Access and Manipulation: Oracle Types vs. Java Types .................................................. 4-32
Data Conversion Considerations ............................................................................................. 4-32
Using Result Set and Statement Extensions ........................................................................... 4-33
Comparing get and set Methods for oracle.sql.* Format with Java Format ...................... 4-34
Using Result Set Meta Data Extensions................................................................................... 4-44
Working with LOBs.......................................................................................................................... 4-45
Getting BLOB and CLOB Locators........................................................................................... 4-46
Passing BLOB and CLOB Locators .......................................................................................... 4-47
Reading and Writing BLOB and CLOB Data ......................................................................... 4-48
Creating and Populating a BLOB or CLOB Column............................................................. 4-52
Accessing and Manipulating BLOB and CLOB Data............................................................ 4-54
Getting BFILE Locators.............................................................................................................. 4-55
Passing BFILE Locators ............................................................................................................. 4-56
Reading BFILE Data ................................................................................................................... 4-57
Creating and Populating a BFILE Column ............................................................................. 4-58
Accessing and Manipulating BFILE Data ............................................................................... 4-60
Working with Oracle Object Types ............................................................................................... 4-62
Using Default Java Classes for Oracle Objects ....................................................................... 4-62
Creating Custom Java Classes for Oracle Objects.................................................................. 4-65
Using JPublisher with JDBC ..................................................................................................... 4-82
Working with Oracle Object References...................................................................................... 4-83
Retrieving an Object Reference................................................................................................. 4-84
Passing an Object Reference to a Callable Statement ............................................................ 4-85
v
Accessing and Updating Object Values through an Object Reference ............................... 4-85
Passing an Object Reference to a Prepared Statement .......................................................... 4-86
Working with Arrays ........................................................................................................................ 4-87
Retrieving an Array and its Elements...................................................................................... 4-88
Passing an Array to a Prepared Statement ............................................................................. 4-93
Passing an Array to a Callable Statement ............................................................................... 4-94
Using a Type Map to Map Array Elements ............................................................................ 4-94
Additional Oracle Extensions......................................................................................................... 4-97
Performance Extensions............................................................................................................. 4-97
Additional Type Extensions.................................................................................................... 4-111
Oracle JDBC Notes and Limitations ........................................................................................... 4-115
5 Advanced Topics
Using NLS ............................................................................................................................................ 5-2
How JDBC Drivers Perform NLS Conversions........................................................................ 5-2
NLS Restrictions............................................................................................................................ 5-5
Working with Applets........................................................................................................................ 5-7
Coding Applets ............................................................................................................................. 5-7
Connecting an Applet to a Database.......................................................................................... 5-9
Using Applets with Firewalls ................................................................................................... 5-14
Packaging Applets ...................................................................................................................... 5-17
Specifying an Applet in an HTML Page.................................................................................. 5-19
Browser Security and JDK Version Considerations .............................................................. 5-20
JDBC on the Server: the Server Driver ......................................................................................... 5-22
Connecting to the Database with the Server Driver .............................................................. 5-22
Session and Transaction Context for the Server Driver ........................................................ 5-23
Testing JDBC on the Server ....................................................................................................... 5-24
Server Driver Support for NLS ................................................................................................. 5-25
Embedded SQL92 Syntax ................................................................................................................ 5-26
Time and Date Literals............................................................................................................... 5-26
Scalar Functions .......................................................................................................................... 5-28
LIKE Escape Characters ............................................................................................................. 5-29
Outer Joins ................................................................................................................................... 5-29
Function Call Syntax .................................................................................................................. 5-30
SQL92 to SQL Syntax Example................................................................................................. 5-30
vi
6 Coding Tips and Troubleshooting
JDBC and Multi-Threading .............................................................................................................. 6-2
Performance Optimization................................................................................................................ 6-5
Disabling Auto-Commit Mode................................................................................................... 6-5
Prefetching Rows.......................................................................................................................... 6-6
Batching Updates.......................................................................................................................... 6-6
Common Problems ............................................................................................................................. 6-6
Space Padding for CHAR Columns Defined as OUT or IN/OUT Variables ...................... 6-7
Memory Leaks and Running Out of Cursors ........................................................................... 6-7
Boolean Parameters in PL/SQL Stored Procedures ................................................................ 6-7
Opening More Than 16 OCI Connections for a Process ......................................................... 6-8
Basic Debugging Procedures............................................................................................................ 6-9
Trapping Exceptions .................................................................................................................... 6-9
Logging JDBC Calls.................................................................................................................... 6-10
Net8 Tracing to Trap Network Events .................................................................................... 6-10
Using Third Party Tools ............................................................................................................ 6-13
Transaction Isolation Levels and the Oracle Server................................................................... 6-13
7 Sample Applications
Sample Applications for Basic JDBC Features ............................................................................. 7-2
Streaming Data.............................................................................................................................. 7-2
Sample Applications for JDBC 2.0-Compliant Oracle Extensions............................................ 7-4
LOB Sample ................................................................................................................................... 7-4
BFILE Sample .............................................................................................................................. 7-10
Sample Applications for Other Oracle Extensions .................................................................... 7-14
REF CURSOR Sample ................................................................................................................ 7-14
Array Sample .............................................................................................................................. 7-16
Creating Customized Java Classes for Oracle Objects............................................................. 7-20
SQLData Sample......................................................................................................................... 7-20
CustomDatum Sample............................................................................................................... 7-26
Creating Signed Applets ................................................................................................................. 7-31
JDBC versus SQLJ Sample Code ................................................................................................... 7-38
SQL Program to Create Tables and Objects............................................................................ 7-39
JDBC Version of the Sample Code ........................................................................................... 7-41
SQLJ Version of the Sample Code............................................................................................ 7-44
vii
8 Reference Information
Valid SQL-JDBC Datatype Mappings ............................................................................................ 8-2
Supported SQL and PL/SQL Datatypes ......................................................................................... 8-4
NLS Character Set Support ............................................................................................................... 8-8
Related Information ........................................................................................................................... 8-8
Oracle JDBC Drivers and SQLJ ................................................................................................... 8-8
Java Technology ............................................................................................................................ 8-8
Signed Applets .............................................................................................................................. 8-9
viii
Send Us Your Comments
JDBC Developer’s Guide and Reference, Release 8.1.5
Part No. A64685-01
Oracle Corporation welcomes your comments and suggestions on the quality and usefulness of this
publication. Your input is an important part of the information used for revision.
■ Did you find any errors?
■ Is the information clearly presented?
■ Do you need more information? If so, where?
■ Are the examples correct? Do you need more examples?
■ What features did you like most about this manual?
If you find any errors or have any other suggestions for improvement, please indicate the chapter,
section, and page number (if available). You can send comments to us in the following ways:
■ Electronic mail — [email protected]
■ FAX - 650-506-7225. Attn: Java Products Group, Information Development Manager
■ Postal service:
Oracle Corporation
Information Development Manager
500 Oracle Parkway, Mailstop 4op978
Redwood Shores, CA 94065
USA
If you would like a reply, please give your name, address, and telephone number below.
If you have problems with the software, please contact your local Oracle World Wide Support Center.
ix
x
Preface
Intended Audience
This manual assumes that you are an experienced programmer and that you
understand Oracle databases, the SQL and Java programming languages, and the
principles of JDBC.
Manual Structure
The JDBC Developers Guide and Reference contains eight chapters and one appendix:
xi
Chapter 3, "Basic Features" This chapter covers the basic steps in creating
any JDBC application. It also discusses
additional basic features of Java and JDBC
supported by the Oracle JDBC drivers.
Chapter 4, "Oracle Extensions" This chapter describes JDBC extensions
provided by Oracle: packages, classes, and
datatypes. It also describes the support for
LOBs, objects, and collections provided by the
extensions.
Chapter 5, "Advanced Topics" This chapter describes advanced JDBC topics
such as using NLS, working with applets, the
server-side driver, and embedded SQL92 syntax.
Chapter 6, "Coding Tips and This chapter includes coding tips and general
Troubleshooting" guidelines for troubleshooting your JDBC
applications.
Chapter 7, "Sample This chapter presents sample applications that
Applications" highlight advanced JDBC features and Oracle
extensions.
Chapter 8, "Reference This chapter contains detailed JDBC reference
Information" information.
Appendix A, "JDBC Error This appendix lists errors that can be thrown by
Messages" the JDBC drivers.
Related Documentation
This manual contains references to the following Oracle publications:
■ Oracle8i JPublisher User’s Guide
This book describes how to use the JPublisher utility to translate object types
and other user-defined types to Java classes. If you are developing SQLJ or
JDBC applications that use object types, varray types, nested table types, or
REF types, then you are required to have Java classes that correspond to these
types. JPublisher helps you do this by creating the mapping between object
types and Java classes, and between object attribute types and their
corresponding Java types.
xii
■ Oracle8i SQLJ Developer’s Guide and Reference
This book describes the use of SQLJ to embed static SQL operations directly into
Java code. Both standard SQLJ features and Oracle-specific SQLJ features are
described.
■ Oracle8i Java Stored Procedures Developer’s Guide
This book describes Java stored procedures, which lets Java programmers
access the Oracle RDBMS. With stored procedures (functions, procedures,
database triggers, and SQL methods), Java developers can implement business
logic at the server level, thereby improving application performance, scalability,
and security.
■ Oracle8i Enterprise JavaBeans and CORBA Developer’s Guide
This manual describes the Oracle extensions to the JavaBeans and CORBA
specifications.
■ Net8 Administrator’s Guide
Refer to this manual for more information about ANO (Advanced Network
Option), the Oracle8 Connection Manager, and about Net8 network
administration in general.
■ Oracle8i Error Messages
Refer to this document set for more information on error messages that can be
passed by the Oracle Database and the Oracle JDBC drivers.
■ Oracle8i National Language Support Guide
Refer to this manual for more information on NLS environment variables,
character sets, territories, and locale data. In addition, it contains an overview of
common NLS issues, some typical scenarios, and some NLS considerations for
OCI and SQL programmers.
■ Oracle8i Application Developer’s Guide - Large Objects (LOBs) and the Oracle8i
Application Developer’s Reference - Packages
These books describe how to access and manipulate large objects (LOBs) using
PL/SQL code and the DBMS_LOB package.
■ Oracle8i SQL Reference
This reference contains a complete description of the content and syntax of the
Structured Query Language (SQL) used to manage information in an Oracle
database.
xiii
■ PL/SQL User’s Guide and Reference
PL/SQL is Oracle’s procedural extension to SQL. An advanced
fourth-generation programming language (4GL), PL/SQL offers seamless SQL
access, tight integration with the Oracle server and tools, portability, security,
and modern software engineering features such as data encapsulation,
overloading, exception handling, and information hiding. This guide explains
all the concepts behind PL/SQL and illustrates every facet of the language.
■ Oracle8i Application Server documentation
Refer to this documentation for more information on how the Oracle8i
Application Server supports JDBC.
■ Oracle8 JDeveloper Suite documentation
Refer to this documentation for more information on how Oracle8 JDeveloper
Suite supports JDBC.
xiv
Conventions Used in this Manual
Solaris syntax is used in this book, but file names and directory names for Windows
NT are the same unless otherwise noted.
The term [ORACLE_HOME] is used to indicate the full path of the Oracle home
directory.
In examples, an implied carriage return occurs at the end of each line, unless
otherwise noted. You must press the Return key at the end of a line of input.
The following conventions are also used in this manual:
Convention Meaning
. Vertical ellipsis points in an example mean that information not
. directly related to the example has been omitted.
.
... Horizontal ellipsis points in statements or commands mean that
parts of the statement or command not directly related to the
example have been omitted
<> Angle brackets enclose user-supplied names.
[] Brackets enclose optional clauses from which you can choose one or
none.
xv
xvi
1
Overview
Overview 1-1
What is JDBC?
What is JDBC?
JDBC (Java Database Connectivity) is a standard Java interface for connecting to
relational databases from Java. The JDBC standard was defined by Sun
Microsystems, allowing individual providers to implement and extend the standard
with their own JDBC drivers.
JDBC is based on the X/Open SQL Call Level Interface, and complies with the
SQL92 Entry Level standard.
In addition to the standard JDBC API, Oracle drivers have extensions to properties,
types, and performance.
in turn, can use JDBC calls. The generated Java code compiles and runs like any
other Java program.
Although SQLJ provides direct support for static SQL operations that are known at
the time the program is written, it can also inter-operate with dynamic SQL through
JDBC. SQLJ allows you to create JDBC objects when they are needed for dynamic
SQL operations. In this way, SQLJ and JDBC can co-exist in the same program.
Convenient conversions are supported between JDBC connections and SQLJ
connection contexts, as well as between JDBC result sets and SQLJ iterators. For
more information on this, see the Oracle8i SQLJ Developer’s Guide and Reference.
The syntax and semantics of SQLJ and JDBC do not depend on the configuration
under which they are running, thus enabling implementation on the client or
database side or in the middle tier.
Overview 1-3
Basic Driver Architecture
■ you want to write an application that you can deploy to another database.
Using SQLJ, you can customize the static SQL for that database at
deployment-time.
■ you are working with a database that contains compiled SQL. You will want to
use SQLJ because you cannot compile SQL statements in a JDBC program.
Use JDBC to write your program when:
■ your program uses dynamic SQL. For example, you have a program that builds
queries on-the-fly or has an interactive component.
■ you do not want to have a SQLJ layer during deployment or development. For
example, you might want to download only the JDBC Thin driver and not the
SQLJ runtime libraries to minimize download time over a slow link.
Oracle 8.1.5
Overview 1-5
Oracle Extensions to the JDBC Standard
The JDBC OCI driver is written in a combination of Java and C because it must
make calls to the OCI libraries. The driver requires the presence of the OCI libraries,
Net8, CORE libraries, and other necessary files on each client machine or
middle-tier application server on which it is installed.
Note: There are special considerations for using the Thin driver
with JDK 1.0.2 and 1.1.1 in the context of applets. See "Working
with Applets" on page 5-7 for more information on this topic.
You can use the JDBC OCI drivers on a middle tier in conjunction with Oracle Web
Application Server versions 3.0 and higher. The Oracle Web Application Server
bundles JDBC with its distribution. For more information on the use of JDBC and
the Oracle Web Application Server, see your Oracle Web Application Server
documentation.
Overview 1-7
JDBC and IDEs
This chapter guides you through the basics of testing your installation and
configuration and running a simple application. The following topics are discussed:
■ Oracle JDBC Drivers
■ Requirements and Compatibilities for Oracle JDBC Drivers
■ Verifying a JDBC Client Installation
Notes:
■ JDBC Thin drivers use a subset of the Net8 protocol, written
entirely in Java, and connect using the TCP/IP protocol.
■ There are other restrictions on applets besides your choice of
JDBC driver. For information on these restrictions, see "Browser
Security and JDK Version Considerations" on page 5-20.
■ If you desire maximum portability, then choose the JDBC Thin driver. You can
connect to an Oracle8 data server from either an application or an applet using
the JDBC Thin driver.
■ If you are writing an application and need maximum performance, then choose
the JDBC OCI driver.
■ If you are running in the Oracle database server using the Oracle 8.1.5 Java VM,
then choose the JDBC Server driver.
■ readme.txt: The readme.txt file contains up to the minute facts about the
drivers that might not be in the manual.
Check that all these directories have been created and populated.
JDBC OCI Drivers: If you are installing the JDBC OCI driver, you must also set the
following value for the library path environment variable (this will be
LD_LIBRARY_PATH on Solaris or PATH on Windows NT).
■ [Oracle Home]/lib
On Solaris, this directory contains the shared object library libocijdbc8.so.
JDBC Thin Drivers: If you are installing the JDBC Thin driver, you do not have to set
any other environment variables.
class JDBCVersion
{
public static void main (String args [])
throws SQLException
{
// Load the Oracle JDBC driver
DriverManager.registerDriver
(new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection
("jdbc:oracle:thin:@host:port:sid","scott","tiger");
class JdbcCheckup
{
public static void main (String args [])
throws SQLException, IOException
{
// Load the Oracle JDBC driver
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
System.out.println ("Connecting...");
Connection conn =
DriverManager.getConnection ("jdbc:oracle:oci8:@" + database,
user, password);
System.out.println ("connected.");
// Create a statement
Statement stmt = conn.createStatement ();
{
return "";
}
}
}
This chapter covers the most basic steps taken in any JDBC application. It also
describes additional basic features of Java and JDBC supported by the Oracle JDBC
drivers. It includes the following topics:
■ First Steps in JDBC
■ Sample: Connecting, Querying, and Processing the Results
■ Datatype Mappings
■ Using Java Streams in JDBC
■ Using Stored Procedures in JDBC Programs
■ Error Messages and JDBC
■ Server-Side Basics
■ Application Basics versus Applet Basics
Importing Packages
Regardless of which Oracle JDBC driver you use, you must include the following
import statements at the beginning of your program.
You will need to add the following Oracle packages to your program when you
want to access the extended functionality provided by the Oracle drivers. However,
they are not required for the example presented in this section:
Because you are using one of Oracle’s JDBC drivers, you declare a specific driver
name string to registerDriver(). You register the driver only once in your Java
application.
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
familiar with this method, continue reading the "Understanding the Forms of
getConnection()" section below.
If you are already familiar with the getConnection() method, you can skip
ahead to either of these sections, depending on the driver you installed:
■ "Opening a Connection for the JDBC OCI Driver" on page 3-6
■ "Opening a Connection for the JDBC Thin Driver" on page 3-7
If you want to specify a database name in the connection, it must be in one of the
following formats:
■ a Net8 keyword-value pair
■ a string of the form <host_name>:<port_number>:<sid> (Thin driver only)
■ a TNSNAMES entry (OCI driver only)
For information on how to specify a keyword-value pair or a TNSNAMES entry, see
your Net8 Administrator’s Guide.
The following example connects user scott with password tiger to a database
with SID orcl through port 1521 of host myhost, using the Thin driver.
Connection conn =
DriverManager.getConnection ("jdbc:oracle:thin:@myhost:1521:orcl",
"scott", "tiger");
If you want to use the default connection for an OCI driver, specify either:
Connection conn = DriverManager.getConnection
("jdbc:oracle:oci8:scott/tiger@");
OR
Connection conn =
DriverManager.getConnection ("jdbc:oracle:oci8:@", "scott", "tiger");
For all JDBC drivers you can also specify the database with a Net8 keyword-value
pair. The Net8 keyword-value pair substitutes for the TNSNAMES entry. The following
example uses the same parameters as the preceding example, but in the
keyword-value format:
Connection conn =
DriverManager.getConnection
(jdbc:oracle:oci8:@MyHostString","scott","tiger");
OR
Connection conn =
DriverManager.getConnection("jdbc:oracle:oci8:@(description=(address=(host=
myhost)(protocol=tcp)(port=1521))(connect_data=(sid=orcl)))",
"scott", "tiger");
The following example connects user scott with password tiger to a database
using the OCI driver. In this case, however, the URL includes the userid and
password, and is the only input parameter.
Connection conn =
DriverManager.getConnection("jdbc:oracle:oci8:scott/tiger@myhost);
In addition to the URL, use an object of the standard Java Properties class as
input. For example:
java.util.Properties info = new java.util.Properties();
info.put ("user", "scott");
info.put ("password","tiger");
info.put ("defaultRowPrefetch","15");
getConnection ("jdbc:oracle:oci8:@",info);
Oracle Extensions to Connection Properties Object Oracle has defined several extensions
to the connection properties that Oracle JDBC drivers support. For more
information on this form of the getConnection() method and the Oracle
extensions to the Properties object, see "Oracle Extensions for Connection
Properties" on page 4-109.
Note that both the ":" and "@" characters are necessary.
For the JDBC OCI driver (as with the Thin driver), you can also specify the database
with a Net8 keyword-value pair. This is less readable than a TNSNAMES entry but
does not depend on the accuracy of the TNSNAMES.ORA file. The Net8 keyword-value
pair also works with other JDBC drivers.
For example, if you want to connect to the database on host myhost that has a
TCP/IP listener up on port 1521, and the SID (system identifier) is orcl, use a
statement such as:
Connection conn =
DriverManager.getConnection("jdbc:oracle:oci8:@(description=(address=(host=
myhost)(protocol=tcp)(port=1521))(connect_data=(sid=orcl)))",
"scott", "tiger");
Note: The JDBC Thin driver supports only the TCP/IP protocol.
For example, use this string if you want to connect to the database on host myhost
that has a TCP/IP listener on port 1521 for the database SID (system identifier)
orcl. You can logon as user scott, with password tiger:
Connection conn =
DriverManager.getConnection
("jdbc:oracle:thin:@myhost:1521:orcl", "scott", "tiger");
You can also specify the database with a Net8 keyword-value pair. This is less
readable than the first version, but also works with the other JDBC drivers.
Connection conn =
DriverManager.getConnection
("jdbc:oracle:thin:@(description=(address=(host=myhost)(protocol=tcp)
(port=1521))(connect_data=(sid=orcl)))", "scott", "tiger");
Note that there is nothing Oracle-specific about this statement; it follows standard
JDBC syntax.
Once again, this is standard JDBC syntax. The next() method returns false when it
reaches the end of the result set. The employee names are materialized as Java
Strings.
When you close a Statement object that a given Connection object creates, the
connection itself remains open.
class JdbcTest {
public static void main (String args []) throws SQLException {
// Load Oracle driver
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
If you want to adapt the code for the OCI driver, replace the Connection
statement with the following:
Connection conn = DriverManager.getConnection ("jdbc:oracle:oci8:@MyHostString",
"scott", "tiger");
Datatype Mappings
The Oracle JDBC drivers support the SQL datatypes required by JDBC 1.22. In
addition, the Oracle JDBC drivers support the Oracle-specific ROWID datatype and
user-defined types of the REF CURSOR category.
For reference, the following table shows the default mappings between JDBC
datatypes, native Java datatypes, SQL datatypes, and the corresponding Java
datatypes defined by Oracle extensions.
The Standard JDBC Datatypes column lists the datatypes supported by the JDBC
1.22 standard. All of these dataypes are defined in the java.sql.Types class.
The Java Native Datatypes column lists the datatypes defined by the Java language.
The SQL Datatypes column lists the SQL datatypes that exist in the database.
The Oracle Extensions—Java Classes that Represent SQL Datatypes column lists the
oracle.sql.* Java types that correspond to each SQL datatype in the database.
These are Oracle extensions that let you retrieve all SQL data in the form of a
oracle.sql.* Java type. Mapping SQL datatypes into the oracle.sql
datatypes lets you store and retrieve data without losing information. Refer to
"Classes of the oracle.sql Package" on page 4-7 for more information on the
oracle.sql.* package.
For a list of all of the Java datatypes to which you can validly map a SQL datatype,
see "Valid SQL-JDBC Datatype Mappings" on page 8-2.
Table 3–1 Mapping Between JDBC, Java Native, and Oracle Datatypes
Standard JDBC Java Native Oracle Extensions—Java Classes
Datatypes Datatypes SQL Datatypes that Represent SQL Datatypes
The JDBC Extensions for SQL Datatypes column lists the types into which Oracle
datatypes should map according to the JDBC 2.0 standard. The class
oracle.jdbc.driver.OracleTypes.* includes the definitions of
Oracle-specific types that do not exist in the JDBC standard and is a superset of
oracle.sql.*.
The Oracle Extensions—Java Classes that Represent SQL Datatypes column lists the
oracle.sql.* Java types that correspond to each SQL datatype in the database.
These are Oracle extensions that let you retrieve all SQL data in the form of a
oracle.sql.* Java type. Refer to "Classes of the oracle.sql Package" on page 4-7
for more information on the oracle.sql.* package.
For a list of all of the Java datatypes to which you can validly map a SQL datatype,
see "Valid SQL-JDBC Datatype Mappings" on page 8-2.
Object Value oracle.jdbc.driver.OracleTypes.STRUCT If there is no entry for the object value in the type map:
■ oracle.sql.STRUCT
If there is an entry for the object value in the type map:
■ customized Java class
You can get LONG and LONG RAW data with any of the three stream types. The driver
performs NLS conversions for you depending on the character set of your database
and the driver. For more information about NLS, see "Using NLS" on page 5-2.
For example, the LONG RAW value 20 is represented in hexadecimal as 14 or "1" "4".
In ASCII, 1 is represented by "49" and "4" is represented by "52". In Unicode, a
padding of zeros is used to separate individual values. So, the hexadecimal value 14
is represented as 0 "1" 0 "4". The Unicode representation is 0 "49" 0 "52".
■ If the driver is JDBC Thin and the database character set is not US7ASCII or
WE8ISO8859P1, then a call to getBinaryStream() returns UTF-8. If the
server-side character set is US7ASCII or WE8ISO8859P1 then the call returns a
US7ASCII stream of bytes.
For more information on how the drivers return data based on character set, see
"Using NLS" on page 5-2.
Table 3–3 summarizes LONG and LONG RAW data conversions for each stream type.
Getting a LONG RAW Data Column with getBinaryStream() This Java example writes the
contents of a LONG RAW column to a file on the local file system. In this case, the
driver fetches the data incrementally.
The following code creates the table that stores a column of LONG RAW data
associated with the name LESLIE:
-- SQL code:
create table streamexample (NAME varchar2 (256), GIFDATA long raw);
insert into streamexample values (’LESLIE’, ’00010203040506070809’);
The following Java code snippet writes the data from the LESLIE LONG RAW column
into a file called leslie.gif:
ResultSet rset = stmt.executeQuery ("select GIFDATA from streamexample where
NAME=’LESLIE’");
In this example the contents of the GIFDATA column are transferred incrementally
in chunk-sized pieces between the database and the client. The InputStream
object returned by the call to getBinaryStream() reads the data directly from the
database connection.
Getting a LONG RAW Data Column with getBytes() This version of the example gets the
content of the GIFDATA column with getBytes() instead of
getBinaryStream(). In this case, the driver fetches all of the data in one call and
stores it in a byte array. The previous code snippet can be rewritten as:
ResultSet rset2 = stmt.executeQuery ("select GIFDATA from streamexample where
NAME=’LESLIE’");
Because a LONG RAW column can contain up to 2 gigabytes of data, the getBytes()
example will probably use much more memory than the getBinaryStream()
example. Use streams if you do not know the maximum size of the data in your
LONG or LONG RAW columns.
example, if you have a very small LONG column, you might want to avoid returning
the data incrementally and instead, return the data in one call.
To avoid streaming, use the defineColumnType() method to redefine the type of
the LONG column. For example, if you redefine the LONG or LONG RAW column as
type VARCHAR or VARBINARY, then the driver will not automatically stream the
data.
If you redefine column types with defineColumnType(), you must declare the
types of all columns in the query. If you do not, executeQuery() will fail. In
addition, you must cast the Statement object to the type
oracle.jdbc.driver.OracleStatement.
As an added benefit, using defineColumnType() saves the driver two round
trips to the database when executing the query. Without defineColumnType(),
the JDBC driver has to request the datatypes of the column types.
Using the example from the previous section, the Statement object stmt is cast to
the OracleStatement and the column containing LONG RAW data is redefined to
be of the type VARBINARAY. The data is not streamed; instead, data is returned by
writing it to a byte array.
//cast the statement stmt to an OracleStatement
oracle.jdbc.driver.OracleStatement ostmt =
(oracle.jdbc.driver.OracleStatement)stmt;
If you try to get a CHAR, VARCHAR, or RAW column as a data stream without
redefining the column type, the JDBC driver will return a Java InputStream, but
no real streaming occurs. In the case of these datatypes, the JDBC driver fully
fetches the data into an in-memory buffer during a call to executeQuery() or
next(). The getXXXStream() entry points return a stream that reads data from
this buffer.
The incoming data for each row has the following shape:
<a date><the characters of the long column><a number>
When you call rset.next(), the JDBC driver stops reading the row data just
before the first character of the LONG column. Then the driver uses
rset.getAsciiStream() to read the characters of the LONG column directly out
of the database connection as a Java stream. The driver reads the NUMBER data from
the third column only after it reads the last byte of the data from the stream.
An exception to this behavior is LOB data, which is also transferred between server
and client as a Java stream. For more information on how the driver treats LOB
data, see "Streaming LOBs and External Files" on page 3-23.
Use the Stream Data after You Access It To recover the data from a column containing a
data stream, it is not enough to get the column; you must read and store its
contents. Otherwise, the contents will be discarded when you get the next column.
Call the Stream Column in SELECT List Order If your query selects multiple columns, the
database sends each row as a set of bytes representing the columns in the SELECT
order. If one of the columns contains stream data, the database sends the entire data
stream before proceeding to the next column.
If you do not use the SELECT list order to access data, then you can lose the stream
data. That is, if you bypass the stream data column and access data in a column that
follows it, the stream data will be lost. For example, if you try to access the data for
the NUMBER column before reading the data from the stream data column, the JDBC
driver first reads then discards the streaming data automatically. This can be very
inefficient if the LONG column contains a large amount of data.
If you try to access the LONG column later in the program, the data will not be
available and the driver will return a "Stream Closed" error. This is illustrated in
the following example:
ResultSet rset = stmt.executeQuery
("select DATECOL, LONGCOL, NUMBERCOL from TABLE");
while rset.next()
{
int n = rset.getInt(3); // This discards the streaming data
InputStream is = rset.getAsciiStream(2);
// Raises an error: stream closed.
}
If you get the stream but do not use it before you get the NUMBER column, the stream
still closes automatically:
ResultSet rset = stmt.executeQuery
("select DATECOL, LONGCOL, NUMBERCOL from TABLE");
while rset.next()
{
InputStream is = rset.getAsciiStream(2); // Get the stream
int n = rset.getInt(3);
// Discards streaming data and closes the stream
}
int c = is.read(); // c is -1: no more characters to read-stream closed
Closing a Stream
You can discard the data from a stream at any time by calling the stream’s close()
method. You can also close and discard the stream by closing its result set or
connection object. You can find more information about the close() method for
data streams in "Bypassing Streaming Data Columns" on page 3-21. For information
on how to avoid closing a stream and discarding its data by accident, see
"Streaming Data Precautions" on page 3-22.
Streaming BLOBs and CLOBs When a query selects one or more CLOB or BLOB
columns, the JDBC driver transfers to the client the data pointed to by the locator.
The driver performs the transfer as a Java stream. To manipulate CLOB or BLOB data
from JDBC, use methods in the Oracle extension classes oracle.sql.BLOB and
oracle.sql.CLOB. These classes provide functionality such as reading from the
CLOB or BLOB into an input stream, writing from an output stream into a CLOB or
BLOB, determining the length of a CLOB or BLOB, and closing a CLOB or BLOB.
For a complete discussion of how to use streaming CLOB and BLOB data, see
"Reading and Writing BLOB and CLOB Data" on page 4-48.
Streaming BFILEs An external file, or BFILE, is used to store a locator to a file that is
outside the database, stored somewhere on the filesystem of the data server. The
locator points to the actual location of the file.
When a query selects one or more BFILE columns, the JDBC driver transfers to the
client the file pointed to by the locator. The transfer is performed in a Java stream.
To manipulate BFILE data from JDBC, use methods in the Oracle extension classes
oracle.sql.BFILE. These classes provide functionality such as reading from the
BFILE into an input stream, writing from an output stream into a BFILE
determining the length of a BFILE, and closing a BFILE.
For a complete discussion of how to use streaming BFILE data, see "Reading BFILE
Data" on page 4-57.
As an example of using Oracle syntax, here is a PL/SQL code snippet that creates a
stored function. The PL/SQL function gets a character and concatenates a suffix to
it:
create or replace function foo (val1 char)
return char as
begin
return val1 || ’suffix’;
end;
CallableStatement cs =
conn.prepareCall ("begin ? := foo(?); end;");
cs.registerOutParameter(1,Types.CHAR);
cs.setString(2, "aa");
cs.executeUpdate();
String result = proc.getString(1);
■ getMessage(): returns the error message associated with the object that threw
the exception
■ printStackTrace(): prints this object name and its stacktrace to the
specified print stream
This example uses both getMessage() and printStackTrace() to return
errors.
catch(SQLException e);
{
System.out.println("exception: " + e.getMessage());
e.printStackTrace();
}
The text of all error messages has been internationalized. That is, they are available
in all of the languages and character sets supported by Oracle. These error messages
are listed in Appendix A, "JDBC Error Messages".
Server-Side Basics
This section has the following subsections:
■ Session and Transaction Context
■ Connecting to the Database
The tutorial presented in "First Steps in JDBC" on page 3-2, describes connecting to
and querying a database using the client-side driver. The following sections
describe some of the basic differences if you run the tutorial using the server-side
driver. For a complete discussion of the server-side driver, see "JDBC on the Server:
the Server Driver" on page 5-22.
Application Basics
You can use either the Oracle JDBC Thin driver or the JDBC OCI driver to create an
application. Because the JDBC OCI driver uses native methods, there can be
significant performance advantages in using this driver for your applications.
An application that can run on a client can run on the server by using the JDBC
Server driver.
If you are using a JDBC OCI driver in an application, then the application will
require an Oracle installation on its clients. For example, the application will require
the installation of Net8 and client libraries.
Applet Basics
This section describes the issues you should take into consideration if you are
writing an applet that uses the JDBC Thin driver.
■ Use Oracle8 Connection Manager on the host machine. The applet can connect
to Oracle8 Connection Manager, which in turn connects to a database on
another machine.
■ Use signed applets. If your browser supports JDK 1.1.x, then you can use signed
applets. Signed applets can request socket connection privileges to other
machines.
Both of these topics are described in greater detail in "Connecting an Applet to a
Database" on page 5-9.
This chapter describes Oracle extensions to standard JDBC, including the following
topics:
■ Introduction to Oracle Extensions
■ Oracle JDBC Packages and Classes
■ Data Access and Manipulation: Oracle Types vs. Java Types
■ Working with LOBs
■ Working with Oracle Object Types
■ Working with Oracle Object References
■ Working with Arrays
■ Additional Oracle Extensions
■ Oracle JDBC Notes and Limitations
Note: The JDBC OCI, Thin, and Server drivers support the same
functionality, and all of the Oracle extensions.
Packages Oracle release 8.1.5 does not support JDK 1.2. The JDBC 2.0 interfaces are
part of the java.sql package that is included with the JDK 1.2. Therefore, to
support JDBC 2.0 types, as well as additional Oracle extensions, the Oracle JDBC
distribution includes the following Java packages:
■ oracle.jdbc2 (a subset of the standard JDBC 2.0 interfaces)
■ oracle.sql (classes to support all Oracle type extensions)
■ oracle.jdbc.driver (classes to support database access and updates in
Oracle type formats)
"Oracle JDBC Packages and Classes" on page 4-6 further describes these packages
and their classes.
Oracle Datatype Support A key feature of the Oracle JDBC extensions is the type
support in the oracle.sql.* package. This package includes classes that map to
all of the Oracle SQL datatypes, acting as wrappers for raw SQL data. This
functionality provides two significant advantages in manipulating SQL data:
■ Accessing data directly in SQL format is more efficient than first converting it to
Java format.
■ Performing mathematical manipulations of the data directly in SQL format
avoids the loss of precision that occurs in converting between SQL and Java
formats.
Once manipulations are complete and it is time to output the information, each of
the oracle.sql.* type support classes has all of the necessary methods to
convert data to appropriate Java formats.
For a more detailed description of these general issues, see "Classes of the oracle.sql
Package" on page 4-7.
Specific information relating to particular oracle.sql.* datatype classes is
discussed in the sections "Working with LOBs" on page 4-45 and "Additional Type
Extensions" on page 4-111.
Oracle Object Support Perhaps the most noteworthy Oracle8 type is Oracle objects.
Oracle8 supports the use of structured objects in the database, where an object
datatype is a user-defined type with nested attributes. For example, a user
application could define an Employee object type, where each Employee object
has a firstname attribute (a character string), a lastname attribute (another
character string), and an employeenumber attribute (integer).
Oracle’s JDBC implementation supports Oracle object datatypes. When you work
with Oracle object datatypes in a Java application you must consider the following:
■ how to map between Oracle object datatypes and Java classes
■ how to store Oracle object attributes in corresponding Java objects (they can be
stored in Java format or in oracle.sql.* format)
■ how to convert attribute data between SQL and Java formats
■ how to access data
To manually create Java classes to correspond to your Oracle objects, Oracle
recommends that you use the Oracle8i JPublisher utility to create the classes. To do
this, you must define attributes according to how you want to store the data.
JPublisher handles this task seamlessly with command-line options.
A type map defines the correspondence between Oracle object datatypes and Java
classes. Type maps are objects of a special Java class that specify which Java class
corresponds to each Oracle object datatype. Oracle JDBC uses these type maps to
determine which Java class to instantiate and populate when it retrieves Oracle
object data from a result set.
Each Java class created to correspond to an Oracle object datatype must implement
one of two supported interfaces: the JDBC-standard SQLData interface or the
Oracle CustomDatum interface. Each of these interfaces specifies methods to
convert data between SQL and Java. Currently, JPublisher supports only the
CustomDatum interface.
JPublisher automatically defines get methods of the Java classes, which retrieve
data into your Java application. For more information on the JPublisher utility, see
the Oracle8i JPublisher User’s Guide.
"Working with Oracle Object Types" on page 4-62 describes Oracle JDBC support for
Oracle objects.
Support for Schema Naming Oracle JDBC classes have the ability to accept and return
fully qualified schema names. A fully qualified schema name has this syntax:
{[schema_name].}[sql_type_name]
where schema_name is the name of the schema and sql_type_name is the SQL
type name of the object. Notice that the schema_name and the sql_type_name is
separated by a dot (".").
To specify an object type in JDBC, you use its fully qualified name (that is, a schema
name and SQL type name). It is not necessary to enter a schema name if the type
name is in current naming space (that is, the current schema). Schema naming
follows these rules:
■ Both the schema name and the type name may or may not be quoted. However,
if the SQL type name has a dot in it, such as CORPORATE.EMPLOYEE, the type
name must be quoted.
■ The JDBC driver looks for the first unquoted dot in the object’s name and uses
the string before the dot as the schema name and the string following the dot as
the type name. If no dot is found, the JDBC driver takes the current schema as
default. That is, you can specify only the type name (without indicating a
schema) instead of specifying the fully qualified name if the object type name
belongs to the current schema. This also explains why you must quote the type
name if the type name has a dot in it.
For example, assume that user Scott creates a type called person.address
and then wants to use it in his session. Scott might want to skip the schema
name and pass in person.address to the JDBC driver. In this case, if
person.address is not quoted, then the dot will be detected, and the JDBC
driver will mistakenly interpret person as the schema name and address as
the type name.
■ JDBC passes the object type name string to the database unchanged. That is, the
JDBC driver will not change the character case even if it is quoted.
For example, if ScOtT.PersonType is passed to the JDBC driver as an object
type name, the JDBC driver will pass the string to the database unchanged. As
another example, if there is white space between characters in the type name
string, then the JDBC driver will not remove the white space.
■ The JDBC driver assumes that schema names do not contain dots (".").
■ The JDBC driver does not allow double quotes (") as part of the schema name or
the type name.
The following sections describe each class listed in Table 4–1. Additional details
about use of the Oracle extended types (STRUCT, REF, ARRAY, BLOB, CLOB, BFILE,
and ROWID) are described in "Working with LOBs" on page 4-45, "Working with
Oracle Object References" on page 4-83, "Working with Arrays" on page 4-87, and
"Additional Type Extensions" on page 4-111.
Notes:
■ Beware of possible confusion between the STRUCT class, used
for objects only, and the general term structured objects, which
often indicates either objects or collections. The ARRAY class
supports collections, which can be either varrays or nested
tables.
■ For information about retrieving data from a result set or
callable statement object into oracle.sql.* types as opposed
to Java types, see "Data Access and Manipulation: Oracle Types
vs. Java Types" on page 4-32.
■ The LONG, LONG RAW, or REF CURSOR SQL types have no
oracle.sql.* classes. Use standard JDBC functionality for
these types. For example, retrieve LONG or LONG RAW data as
input streams using the standard JDBC methods
getAsciStream(), getBinaryStream(), and
getUnicodeStream(). Use getCursor() for REF CURSOR
types.
Refer to the Javadoc for additional information about these classes. The rest of this
section further describes the oracle.sql.* classes.
Class oracle.sql.STRUCT
For any given Oracle object type, if you do not specify a mapping to a Java class in
your connection’s type map, data from the object type will be materialized in Java
in an instance of the oracle.sql.STRUCT class.
The STRUCT class implements the standard JDBC 2.0 oracle.jdbc2.Struct
class and extends oracle.sql.Datum.
In the database, Oracle stores the raw bytes of object data in a linearized form. A
STRUCT object is a wrapper for the raw bytes of an Oracle object and contains a
"values" array of oracle.sql.Datum objects holding the attribute values in SQL
format. The STRUCT object also contains the SQL type name of the Oracle object.
In most cases you will probably want to create a custom Java type definition class to
map to your Oracle object, although using the STRUCT class may suffice in some
cases (see "Using STRUCT Objects" on page 4-63). The attributes of a STRUCT can be
materialized as java.lang.Object[] objects if you use the getAttributes()
method, or as oracle.sql.Datum[] objects if you use the
getOracleAttributes() method. The oracle.sql.* format gives you the
same advantages as using oracle.sql.* datatype classes in general:
■ The STRUCT class completely preserves data, because it maintains the data in
SQL format. This is useful if you want to manipulate data but not necessarily
display it.
■ It allows complete flexibility in how your Java application unpacks data.
Notes:
■ Elements of the values array, although of the generic Datum
type, would actually contain data associated with the relevant
oracle.sql.* type appropriate for the given attribute, such
as oracle.sql.CHAR in the case of CHAR data. You can cast
an element as the appropriate oracle.sql.* type as desired.
■ The JDBC driver materializes nested objects in the values array
of a STRUCT object as instances of STRUCT themselves.
■ Refer to the Javadoc for more information about particular
features and methods of the oracle.sql.STRUCT class.
In some cases you might want to manually create a STRUCT object to pass it to a
prepared statement or callable statement. To do this, you must also create a
StructDescriptor object. For more information on creating a STRUCT object, see
"Creating STRUCT Objects and Descriptors" on page 4-13.
The STRUCT class includes the following methods:
■ getAttributes(): retrieves the values from the values array, using the type
map (if one has been defined) to determine which Java classes to use in
materializing the data. Conceptually, getAttributes() returns a Java array
containing the attribute values. The types of the attribute values are those that a
call to getObject() on the same underlying types will return. That is, they are
the "default" JDBC types for the corresponding underlying types.
For example, assume that you have defined a SQL type PERSON with a name
attribute of type CHAR and an age attribute of type NUMBER. If you use
getAttributes() to get the object attributes of PERSON, then it will return
the name as a Java String type and the age as a Java BigDecimal type.
where sql_type_name is a Java string containing the name of the Oracle object
type (such as EMPLOYEE) and connection is your connection object.
You can also call the StructDescriptor object if you need to create a new
STRUCT object. To construct a new StructDescriptor object, pass in a Java string
parameter with the SQL type name of the Oracle object type and your connection
object:
StructDescriptor structdesc = new StructDescriptor(sql_type_name, connection);
The StructDescriptor class includes the getName() method to return the fully
qualified SQL type name of the Oracle object (that is, in schema.sql_type_name
format. For example, CORPORATE.EMPLOYEE)
Embedded Objects The JDBC driver seamlessly handles embedded objects (STRUCT
objects that are attributes of STRUCT objects) in the same way that it normally
handles objects. When the JDBC driver retrieves an attribute that is an object, it
follows the same rules of conversion, using the type map if it is available, or else
using default mapping.
Class oracle.sql.REF
The oracle.sql.REF class is the generic class that supports Oracle object
references. This class, as with all of the oracle.sql.* datatype classes, is a
subclass of oracle.sql.Datum. It implements the standard JDBC 2.0
oracle.jdbc2.Ref interface.
Selecting a REF retrieves only a pointer to an object; it does not materialize the
object. However, there are methods to accomplish this.
The oracle.sql.REF class includes the following methods:
■ getValue(): retrieves object attributes (using your type map as necessary)
■ setValue(): sets object attributes (using your type map as necessary)
■ getBaseTypeName(): retrieves the fully-qualified SQL structured type name
of the referenced item
The setREF() and setRef() methods of the OraclePreparedStatement and
OracleCallableStatement classes support passing a REF object as an input
parameter to a prepared statement. Similarly, the getREF() and getRef()
methods of the OracleCallableStatement and OracleResultSet support
passing a REF object as an output parameter.
You cannot create REF objects using JDBC.
For more information on how to use REF objects, see "Working with Oracle Object
References" on page 4-83.
Class oracle.sql.ARRAY
The oracle.sql.ARRAY class supports Oracle collections, either varrays or
nested tables. If you select either a varray or nested table from the database, then
the JDBC driver materializes it as an object of the ARRAY class; the structure of the
data is equivalent in either case. The oracle.sql.ARRAY class extends
Note: The name of the collection type has nothing to do with the
type name of the elements. For example:
CREATE TYPE person AS object (c1 NUMBER(5), c2
VARCHAR2(30));
CREATE TYPE array_of_persons AS varray(10) OF
person;
in the preceding statements, the SQL type name of the collection
type is array_of_persons. The SQL type name of the elements
of the collection is person.
where sql_type_name is the type name of the array and connection is your
Connection object.
To construct an ARRAY object, pass in the array descriptor, your connection object,
and a Java object containing the individual elements you want the array to contain.
ARRAY array = new ARRAY(arraydesc, connection, elements);
Notes:
■ The setARRAY(), setArray(), and setObject() methods
of the OraclePreparedStatement class take an object of the
type oracle.sql.ARRAY as an argument, not an array of
objects.
■ Refer to the Javadoc for more information about the features of
the ARRAY and ArrayDescriptor classes.
■ CLOBs point to large fixed-width character data items (that is, characters that
require a fixed number of bytes per character) and are supported by the
oracle.sql.CLOB class.
■ BFILEs point to the content of external files (operating system files) and are
supported by the oracle.sql.BFILE class.
You can select a BLOB, CLOB, or BFILE locator from the database using a standard
SELECT statement, but bear in mind that you are receiving only the locator, not the
data itself. Additional steps are necessary to retrieve the data. This is described in
"Working with LOBs" on page 4-45.
Note: You cannot write to a BFILE; you can only read from it.
Class oracle.sql.CHAR
The CHAR class has special functionality for NLS conversion of character data. A key
attribute of the CHAR class, and a parameter always passed in when a CHAR object is
constructed, is the NLS character set used in presenting the character data. Without
the character set being known, the bytes of data in the CHAR object are meaningless.
CHAR objects that the driver constructs and returns can be in the database character
set, UTF-8, or ISO-Latin-1 (WE8ISO8859P1). CHAR objects which are Oracle8
objects, are returned in the database character set.
JDBC constructs and populates CHAR objects once character data has been read from
the database. Additionally, you might want to construct a CHAR object yourself (to
pass in to a prepared statement, for example).
When you construct a CHAR object, you must provide character set information to
the CHAR object by way of an instance of the oracle.sql.CharacterSet class.
Each instance of the CharacterSet class represents one of the NLS character sets
that Oracle supports. A CharacterSet instance encapsulates methods and
attributes of the character set, mainly involving functionality to convert to or from
other character sets. You can find a complete list of the character sets that Oracle
supports in the Oracle8i National Language Support Guide.
If you use a CHAR object based on a character set that Oracle does not support, then
the JDBC driver will not be able to perform character set conversions with it. For
example, you will not be able to use the CHAR object in an
OraclePreparedStatement.setOracleObject() call.
Follow these general steps to construct a CHAR object:
1. Create a CharacterSet instance by calling the static CharacterSet.make()
method. This method is a factory for the character set class. It takes as input an
integer OracleId, which corresponds to a character set that Oracle supports.
For example:
int oracleId = CharacterSet.JA16SJIS_CHARSET; // this is character set 832
...
CharacterSet mycharset = CharacterSet.make(OracleId);
Each character set that Oracle supports has a unique predefined OracleId. If
you enter an invalid OracleId, an exception will not be thrown. Instead, when
you try to use the character set, you will receive unpredictable results. For more
information on character sets and character set IDs, see the Oracle8i National
Language Support Guide.
2. Construct a CHAR object. Pass to the constructor a string (or the bytes that
represent the string) and the CharacterSet object that indicates how to
interpret the bytes based on the character set. For example:
String mystring = "teststring";
...
CHAR mychar = new CHAR(teststring, mycharset);
The CHAR class has multiple constructors: they can take a string, a byte array, or
an object as input along with the CharacterSet object. In the case of a string,
Notes:
■ The CharacterSet object cannot be null.
■ The CharacterSet class is an abstract class, therefore it has
no constructor. The only way to create instances is through use
of the make() method.
■ The server recognizes the special value
CharacterSet.DEFAULT_CHARSET as the database character
set. For the client, this value is not meaningful.
■ Oracle does not intend or recommend that users extend the
CharacterSet class.
The CHAR class provides these methods for translating character data to strings:
■ getString(): converts the sequence of characters represented by the CHAR
object to a string, returning a Java String object. If the character set is not
recognized (that is, if you entered an invalid OracleID), then getString()
throws a SQLException.
■ toString(): identical to getString(), but if the character set is not
recognized (that is, if you entered an invalid OracleID), then toString()
returns a hexadecimal representation of the CHAR data and does not throw a
SQLException.
■ getStringWithReplacement(): identical to getString(), except a default
replacement character replaces characters that have no Unicode representation
in the character set of this CHAR object. This default character varies from
character set to character set, but is often a question mark.
The server (database) and the client (or application running on the client) can use
different character sets. When you use the methods of this class to transfer data
between the server and the client, the JDBC drivers must convert the data from the
server character set to the client character set (or vice versa). To convert the data, the
drivers use Oracle’s National Language Support (NLS). For more information on
how the JDBC drivers convert between character sets, see "Using NLS" on page 5-2.
For more information on NLS, see the Oracle8i National Language Support Guide.
Class oracle.sql.ROWID
This class supports Oracle ROWIDs, which are unique identifiers for rows in
database tables. You can select a ROWID as you would select any column of data
from the table. Note, however, that you cannot manually update ROWIDs; the Oracle
database updates them automatically as appropriate.
The oracle.sql.ROWID class does not implement any noteworthy functionality
beyond what is in the oracle.sql.Datum superclass. However, ROWID does
provide a stringValue() method that overrides the stringValue() method in
the oracle.sql.Datum class and returns the hexadecimal representation of the
ROWID bytes.
For information about accessing ROWID data, see "Additional Oracle Extensions" on
page 4-97.
Class oracle.jdbc.driver.OracleDriver
Use this class to register the Oracle JDBC drivers for use by your application. You
can input a new instance of this class to the static registerDriver() method of
the java.sql.DriverManager class so that your application can access and use
the Oracle drivers. The registerDriver() method takes as input a "driver" class;
that is, a class that implements the java.sql.Driver interface, as is the case with
OracleDriver.
Once you register the Oracle JDBC drivers, you can create your connection using
the DriverManager class. For more information on registering drivers and writing
a connection string, see "First Steps in JDBC" on page 3-2.
Class oracle.jdbc.driver.OracleConnection
This class extends standard JDBC connection functionality to create and return
Oracle statement objects, set flags and options for Oracle performance extensions,
and support type maps for Oracle objects.
"Performance Extensions" on page 4-97 describes the performance extensions,
including row prefetching, update batching, and metadata TABLE_REMARKS
reporting.
Key methods include:
■ createStatement(): allocates a new OracleStatement object
■ prepareStatement(): allocates a new OraclePreparedStatement object
■ prepareCall(): allocates a new OracleCallableStatement object
■ getTransactionIsolation(): gets this connection’s current isolation mode
■ setTransactionIsolation(): changes the transaction isolation level using
one of the TRANSACTION_* values
These oracle.jdbc.driver.OracleConnection methods are Oracle-defined
extensions:
■ getDefaultExecuteBatch(): retrieves the default update-batching value
for this connection
■ setDefaultExecuteBatch(): sets the default update-batching value for this
connection
■ getDefaultRowPrefetch(): retrieves the default row-prefetch value for this
connection
Class oracle.jdbc.driver.OracleStatement
This class extends standard JDBC statement functionality and is the superclass of
the OraclePreparedStatement and OracleCallableStatement classes.
Extended functionality includes support for setting flags and options for Oracle
performance extensions on a statement-by-statement basis, as opposed to the
OracleConnection class that sets these on a connection-wide basis.
"Performance Extensions" on page 4-97 describes the performance extensions,
including row prefetching and column type definitions.
Key methods include:
■ executeQuery(): executes a database query and returns an
OracleResultSet object
■ getResultSet(): retrieves an OracleResultSet object
■ close(): closes the current statement
These oracle.jdbc.driver.OracleStatement methods are Oracle-defined
extensions:
■ defineColumnType(): defines the type you will use to retrieve data from a
particular database table column
■ getRowPrefetch(): retrieves the row-prefetch value for this statement
■ setRowPrefetch(): sets the row-prefetch value for this statement
Class oracle.jdbc.driver.OraclePreparedStatement
This class extends standard JDBC prepared statement functionality, is a subclass of
the OracleStatement class, and is the superclass of the
Class oracle.jdbc.driver.OracleCallableStatement
This class extends standard JDBC callable statement functionality and is a subclass
of the OracleStatement and OraclePreparedStatement classes. Extended
functionality includes set methods for binding structured objects and
oracle.sql.* objects into prepared statements, and get methods for retrieving
data into oracle.sql.* objects.
Key methods include:
■ getOracleObject(): a generic get method for retrieving data into an
oracle.sql.Datum object. It can be cast to the specific oracle.sql.* type
as necessary.
■ getXXX(): get methods, such as getCLOB(), for retrieving data into specific
oracle.sql.* objects. For more information on all of the getXXX() methods
available for oracle.sql.* types, see the Javadoc.
Class oracle.jdbc.driver.OracleResultSet
This class extends standard JDBC result set functionality, implementing get
methods for retrieving data into oracle.sql.* objects.
Key methods include:
■ getOracleObject(): a generic get method for retrieving data into an
oracle.sql.Datum object. It can be cast to the specific oracle.sql.* type
as necessary.
■ getXXX(): get methods, such as getCLOB(), for retrieving data into
oracle.sql.* objects
■ next(): advances to the next row of the result set
Class oracle.jdbc.driver.OracleResultSetMetaData
This class extends standard JDBC result set metadata functionality to retrieve
information about Oracle result set objects.
Key methods include the following:
■ getColumnCount(): returns the number of columns in an Oracle result set
■ getColumnName(): returns the name of a specified column in an Oracle result
set
■ getColumnType(): returns the SQL type of a specified column in an Oracle
result set. If the column stores an Oracle object or collection, then this method
returns OracleTypes.STRUCT or OracleTypes.ARRAY respectively.
■ getColumnTypeName(): returns the SQL type name of the data stored in the
column. If the column stores an array or collection, then this method returns its
SQL type name. If the column stores REF data, then this method returns the
SQL type name of the objects to which the REF points.
■ getTableName(): returns the name of the table from which an Oracle result
set column was selected
Class oracle.jdbc.driver.OracleTypes
The OracleTypes class defines constants that JDBC uses to identify SQL types.
Each variable in this class has a constant integer value. The
oracle.jdbc.driver.OracleTypes class contains a copy of the standard Java
java.sql.Types class and contains these additional Oracle type extensions:
■ OracleTypes.STRUCT
■ OracleTypes.REF
■ OracleTypes.ARRAY
■ OracleTypes.BLOB
■ OracleTypes.CLOB
■ OracleTypes.BFILE
■ OracleTypes.ROWID
As in java.sql.Types, all of the variable names are in all-caps.
JDBC uses the SQL types identified by the elements of the OracleTypes class in
two main areas: registering output parameters and in the setNull() method of
the PreparedStatement class.
OracleTypes and Registering Output Parameters The SQL types in the OracleTypes
class identify the SQL type of the output parameters in the
registerOutParameter() method of the java.sql.CallableStatement
and oracle.jdbc.driver.OracleCallableStatement classes.
These are the forms that registerOutputParameter() can take for
CallableStatement and OracleCallableStatement:
CallableStatement.registerOutParameter(int index, int sqlType)
In these prototypes, index represents the parameter index, sqlType represents the
SQL datatype (one of the OracleTypes, in this case), sql_name represents the
name given to the datatype (that is, the "named type"), and scale represents the
number of digits to the right of the decimal point when sqlType is a NUMERIC or
DECIMAL datatype.
Any output parameter datatype except STRUCT, ARRAY, or REF can use the two
forms of CallableStatement.registerOutParameter().
The OracleCallableStatement form of registerOutParameter() can be
used only when the output parameter is of type STRUCT, ARRAY, or REF and
requires you to provide the name of the named type.
The following example uses a CallableStatement to call a procedure named
procout, which returns a CHAR datatype. Note the use of the OracleTypes.CHAR
SQL name in the registerOutParameter() method.
CallableStatement procout = conn.prepareCall ("BEGIN procout (?); END;");
procout.registerOutParameter (1, OracleTypes.CHAR);
procout.execute ();
System.out.println ("Out argument is: " + procout.getString (1));
OracleTypes and the setNull() Method The SQL types in the OracleTypes class
identify the object, which the setNull() method sets to NULL. The setNull()
method can be found in the java.sql.PreparedStatement and
oracle.jdbc.driver.OraclePreparedStatement classes.
These are the forms that setNull() can take for PreparedStatement and
OraclePreparedStatement classes:
PreparedStatement.setNull(int index, int sqlType)
In these prototypes, index represents the parameter index, sqlType represents the
SQL datatype (one of the OracleTypes, in this case), and sql_name represents
the name given to the datatype (that is, the name of the "named type"). If you enter
an invalid sqlType, a "Parameter Type Conflict" error is thrown.
You can use the PreparedStatement form of setNull() to set to NULL the
value of an object of any datatype, except STRUCT, ARRAY, or REF.
You can use the OraclePreparedStatement form of setNull() only when you
set to NULL the value of an object of datatype STRUCT, ARRAY, or REF.
The following example uses a PreparedStatement to insert a NULL numeric
value into the database. Note the use of OracleTypes.NUMERIC to identify the
numeric object that is set to NULL.
PreparedStatement pstmt =
In this example, the prepared statement inserts a NULL STRUCT object of type
EMPLOYEE into the database. Note that an OraclePreparedStatement is
required to set a STRUCT object to NULL. Thus, the prepared statement pstmt must
be cast to OraclePreparedStatement.
PreparedStatement pstmt =
conn.prepareStatement ("INSERT INTO employee_table VALUES (?)");
format, you must represent the data in one of the Java formats instead of as an
oracle.sql.*.
If you need the extended functionality provided by the Oracle extensions to JDBC,
you can select the results into a standard ResultSet object, as above, and then cast
that object into an OracleResultSet object later.
Similarly, when you want to execute a stored procedure using a callable statement,
the JDBC drivers will return an OracleCallableStatement object typed as a
java.sql.CallableStatement. If you want to apply only standard JDBC
methods to the object, then keep it as a CallableStatement type. However, if
you want to use the Oracle extensions on the object, you must cast it to an
OracleCallableStatement type. The object is unchanged. The type by which
the Java compiler identifies the object is changed.
You use the standard JDBC java.sql.Connection.prepareStatement()
method to create a PreparedStatement object. If you want to apply only
standard JDBC methods to the object, keep it as a PreparedStatement type.
However, if you want to use the Oracle extensions on the object, you must cast it to
an OraclePreparedStatement type. The object is unchanged. The type by
which the Java compiler identifies the object is changed.
Key extensions to the result set and statement classes include
getOracleObject() and setOracleObject() methods that you can use to
access and manipulate data in oracle.sql.* formats instead of standard Java
formats. For more information see the next section: "Comparing get and set
Methods for oracle.sql.* Format with Java Format".
Comparing get and set Methods for oracle.sql.* Format with Java Format
This section describes get and set methods, particularly the JDBC standard
getObject() and setObject() methods and the Oracle-specific
getOracleObject() and setOracleObject() methods, and how to access
data in oracle.sql.* format compared with Java format.
Although there are specific getXXX() methods for all of the Oracle SQL types (as
described in "Other getXXX() Methods" on page 4-37), you can use the general get
methods for convenience or simplicity, or if you are not certain in advance what
type of data you will receive.
When you have retrieved data into a Datum object, you can use the standard Java
instanceOf() operator to determine which oracle.sql.* type it really is.
For more information on getOracleObject() return types, see Table 4–3,
"Summary of getObject() and getOracleObject() Return Types" on page 4-36.
Example: Using getOracleObject() with a ResultSet The following example creates a table
that contains a column of character data (in this case, a row number) and a column
containing a BFILE locator. A SELECT statement gets the contents of the table into a
result set. The getOracleObject() then retrieves the CHAR data into the
char_datum variable and the BFILE locator into the bfile_datum variable. Note
that because getOracleObject() returns a Datum object, the results must be cast
to CHAR and BFILE respectively.
stmt.execute ("CREATE TABLE bfile_table (x varchar2 (30), b bfile)");
stmt.execute ("INSERT INTO bfile_table VALUES (’one’, bfilename (’TEST_DIR’,
’file1’))");
For information on type compatibility between all SQL and Java types, see
Table 8–1, "Valid SQL Datatype-Java Class Mappings" on page 8-2.
Some of these extensions are taken from the JDBC 2.0 specification. They return
objects of type oracle.jdbc2.* instead of oracle.sql.*. For example,
compare the prototypes:
oracle.jdbc2.Blob getBlob(int parameter_index)
Example: Casting Return Values This example assumes that you have fetched data of
type CHAR into a result set (where it is in column 1). Because you want to
manipulate the CHAR data without losing precision, cast your result set to an
OracleResultSet ors and use getOracleObject() to return the CHAR data.
(If you do not cast your result set, you have to use getObject(), which returns
your character data into a Java String and loses some of the precision of your SQL
data.) By casting the result set, you can use getOracleObject() and return data
in oracle.sql.* format.
The getOracleObject() method returns an oracle.sql.CHAR object into an
oracle.sql.Datum return variable unless you cast the output. Cast the
getOracleObject() output to oracle.sql.CHAR if you want to use a CHAR
return variable and later use any special functionality of that class (such as the
getCharacterSet() method that returns the character set used to represent the
characters).
CHAR char = (CHAR)ors.getOracleObject(1);
CharacterSet cs = char.getCharacterSet();
For some prepared statement ps, the setOracleObject() method binds the
oracle.sql.CHAR data represented by the charVal variable to the prepared
statement. To bind the oracle.sql.* data, the prepared statement must be cast to
an OraclePreparedStatement. Similarly, the setObject() method binds the
Java String data represented by the variable strVal.
PreparedStatement ps= conn.prepareStatement("text_of_prepared_statement");
((OraclePreparedStatement)ps).setOracleObject(1,charVal);
ps.setObject(2,strVal);
object references, and arrays. For example, there is a setBlob() method that takes
an oracle.jdbc2.Blob input parameter, and a setBLOB() method that takes an
oracle.sql.BLOB input parameter.
Similarly, there are two forms of the setNull() method:
■ void setNull(int parameterIndex, int sqlType)
behaves in a similar way to the standard Java
java.sql.PreparedStatement.setNull(). This method takes a
parameter index and a SQL type code defined by java.sql.Types. You use
this method to set an object (except for REFs, ARRAYs, or STRUCTs) to NULL.
■ void setNull(int parameterIndex, int sqlType, String sql_type_name)
takes a SQL type name in addition to a parameter index and a SQL type code.
You use this method only when the SQL type code is REF, ARRAY, or STRUCT.
Similarly, the OracleCallableStatement.registerOutParameter() method
also has an overloaded method that you use when working with REFs, ARRAYs, or
STRUCTs.
void registerOutParameter(int parameterIndex, int sqlType, String
sql_type_name)
For information on type compatibility between all SQL and Java types, see
Table 8–1, "Valid SQL Datatype-Java Class Mappings" on page 8-2.
while (rset.next())
{
OracleResultSetMetaData orsmd = ((OracleResultSet)rset).getMetaData();
int numColumns = orsmd.getColumnCount();
System.out.println("Num of columns = " + numColumns);
■ oracle.sql.BFILE
The oracle.sql.BLOB and CLOB classes implement the oracle.jdbc2.Blob
and Clob interfaces, respectively. In contrast, BFILEs have no oracle.jdbc2
interface.
Instances of these classes contain only the locators for these datatypes, not the data.
After accessing the locators, you must perform some additional steps to access the
data. These steps are described in "Reading and Writing BLOB and CLOB Data" on
page 4-48 and "Reading BFILE Data" on page 4-57.
Notes:
■ If using getObject() or getOracleObject(), then
remember to cast the output as necessary. For more
information, see "Casting Your get Method Return Values" on
page 4-39.
■ Refer the Javadoc for more information about specific features
of the oracle.sql.BLOB and oracle.sql.CLOB classes.
Example: Getting BLOB and CLOB Locators from a Result Set Assume the database has a
table called lob_table with a column for a BLOB locator, blob_col, and a
column for a CLOB locator, clob_col. This example assumes that you have already
created the Statement object, stmt.
First, select the LOB locators into a standard result set, then get the LOB data into
appropriate Java classes:
// Select LOB locator into standard result set.
ResultSet rs =
stmt.executeQuery ("SELECT blob_col, clob_col FROM lob_table");
while (rs.next())
{
// Get LOB locators into Java wrapper classes.
oracle.jdbc2.Blob blob = (oracle.jdbc2.Blob)rs.getObject(1);
oracle.jdbc2.Clob clob = (oracle.jdbc2.Clob)rs.getObject(2);
[...process...]
}
Example: Getting a CLOB Locator from a Callable Statement The callable statement
methods for retrieving LOBs are identical to the result set methods. In the case of a
callable statement, register the output parameter as OracleTypes.BLOB or
OracleTypes.CLOB.
For example, if you have an OracleCallableStatement ocs that calls a
function func that has a CLOB output parameter, then set up the callable statement
as follows:
OracleCallableStatement ocs =
(OracleCallableStatement)conn.prepareCall("{? = call func()}")
ocs.registerOutParameter(1, OracleTypes.CLOB);
ocs.executeQuery()
oracle.sql.CLOB clob = ocs.getCLOB(1);
setCLOB() method, as appropriate. These methods take the parameter index and a
BLOB object or CLOB object as input.
Notes:
■ The implementation of the data access API uses direct native
calls in the JDBC OCI and Server drivers, thereby providing
better performance. You can use the same API on the LOB
classes in all Oracle 8.1.5 JDBC drivers.
■ In the case of the JDBC Thin driver only, the implementation of
the data access API uses the DBMS_LOB package internally. You
never have to use DBMS_LOB directly. This is in contrast to the
8.0.x drivers. For more information on the DBMS_LOB package,
see the Oracle8i Application Developer’s Guide - Large Objects
(LOBs) and the Oracle8i Application Developer’s Reference -
Packages.
To read and write LOB data, you can use these methods:
■ To read from a BLOB, use the getBinaryStream() method of an
oracle.sql.BLOB object to retrieve the entire BLOB as an input stream. This
returns a java.io.InputStream object.
As with any InputStream object, use one of the overloaded read() methods
to read the LOB data and use the close() method when you finish.
■ To write to a BLOB, use the getBinaryOutputStream() method of an
oracle.sql.BLOB object to retrieve the BLOB as an output stream. This
returns a java.io.OutputStream object to be written back to the BLOB.
As with any OutputStream object, use one of the overloaded write()
methods to update the LOB data and use the close() method when you finish.
■ To read from a CLOB, use the getAsciiStream() or
getCharacterStream() method of an oracle.sql.CLOB object to retrieve
the entire CLOB as an input stream. The getAsciiStream() method returns
an ASCII input stream in a java.io.InputStream object; the
getCharacterStream() method returns a Unicode input stream in a
java.io.Reader object.
As with any InputStream or Reader object, use one of the overloaded
read() methods to read the LOB data and use the close() method when you
finish.
Notes:
■ The stream "write" methods described in this section write
directly to the database when you write to the output stream.
You do not need to execute an UPDATE/COMMIT to write the
data.
■ When writing to or reading from a CLOB, the JDBC drivers
handle all character set conversions for you.
// Read CLOB data from CLOB locator into Reader char stream.
Reader char_stream = my_clob.getCharacterStream();
char [] char_array = new char [10];
int chars_read = char_stream.read (char_array, 0, 10);
...
The next example reads a vector of data into a byte array, then uses the
getAsciiOutputStream() method to write the array of ASCII data to a CLOB.
Because getAsciiOutputStream() returns an ASCII output stream, you must
cast the output to a oracle.sql.CLOB datatype.
java.io.OutputStream out
You create a BLOB or CLOB column in a table with the SQL CREATE TABLE
statement. Then, you populate the LOB. This includes creating the LOB entry in the
table, obtaining the LOB locator, creating a file handler for the data (if you are
reading the data from a file), and then copying the data into the LOB.
example assumes that you have already created your Connection object conn and
Statement object stmt:
String cmd = "CREATE TABLE my_blob_table (x varchar2 (30), c blob)";
stmt.execute (cmd);
In this example, the VARCHAR2 column designates a row number, such as one or
two, and the blob column stores the locator of the BLOB data.
3. Declare a file handler for the john.gif file, then print the length of the file.
This value will be used later to ensure that the entire file is read into the BLOB.
Next, create a FileInputStream object to read the contents of the GIF file,
and an OutputStream object to retrieve the BLOB as a stream.
File binaryFile = new File("john.gif");
System.out.println("john.gif length = " + binaryFile.length());
FileInputStream instream = new FileInputStream(binaryFile);
OutputStream outstream = blob.getBinaryOutputStream();
4. Call getChunkSize() to determine the ideal chunk size to write to the BLOB,
then create the buffer byte array.
int chunk = blob.getChunkSize();
byte[] buffer = new byte[chunk];
int length = -1;
5. Use the read() method to read the GIF file to the byte array buffer, then use
the write() method to write it to the BLOB. When you finish, close the input
and output streams.
while ((length = instream.read(buffer)) != -1)
outstream.write(buffer, 0, length);
instream.close();
outstream.close();
Once your data is in the BLOB or CLOB, you can manipulate the data. This is
described in the following section, "Accessing and Manipulating BLOB and CLOB
Data".
Notes:
■ In the OracleResultSet and OracleCallableStatement
classes, getBFILE() and getBfile() both return
oracle.sql.BFILE. There is no oracle.jdbc2 class for
BFILE.
■ If using getObject() or getOracleObject(), remember to
cast the output, as necessary. For more information, see
"Casting Your get Method Return Values" on page 4-39.
Example: Getting a BFILE locator from a Result Set Assume that the database has a table
called bfile_table with a single column for the BFILE locator bfile_col. This
example assumes that you have already created your Statement object stmt.
Select the BFILE locator into a standard result set. If you cast the result set to an
OracleResultSet, you can use getBFILE() to get the BFILE data:
// Select the BFILE locator into a result set
ResultSet rs = stmt.executeQuery("SELECT bfile_col FROM bfile_table");
while (rs.next())
{
oracle.sql.BFILE my_bfile = ((OracleResultSet)rs).getBFILE(1);
};
Note that as an alternative, you can use getObject() to return the BFILE locator.
In this case, since getObject() returns a java.lang.Object, cast the results to
BFILE. For example:
oracle.sql.BFILE my_bfile = (BFILE)rs.getObject(1);
Example: Getting a BFILE Locator from a Callable Statement Assume you have an
OracleCallableStatement ocs that calls a function func that has a BFILE
output parameter. The following code example sets up the callable statement,
registers the output parameter as OracleTypes.BFILE, executes the statement,
and retrieves the BFILE locator:
OracleCallableStatement ocs =
(OracleCallableStatement)conn.prepareCall("{? = call func()}")
ocs.registerOutParameter(1, OracleTypes.BFILE);
ocs.execute();
oracle.sql.BFILE bfile = ocs.getBFILE(1);
Example: Passing a BFILE Locator to a Prepared Statement You want to insert a BFILE
locator into a table. Assume that you have an OraclePreparedStatement ops
where the first parameter is a string (to designate a row number), its second
parameter is a BFILE, and you have a valid oracle.sql.BFILE object (bfile).
Input the BFILE to the prepared statement as follows:
OraclePreparedStatement ops =
(OraclePreparedStatement)conn.prepareStatement
("INSERT INTO my_bfile_table VALUES (?,?)");
ops.setString(1,"one");
ops.setBFILE(2, bfile);
ops.execute();
OracleCallableStatement cstmt =
(OracleCallableStatement)
conn.prepareCall ("begin ? := myGetFileLength (?); end;");
try
{
cstmt.registerOutParameter (1, Types.NUMERIC);
cstmt.setBFILE (2, bfile);
cstmt.execute ();
return cstmt.getLong (1);
}
finally
{
cstmt.close ();
}
}
Notes:
■ BFILEs are read-only. You cannot insert data or otherwise write
to a BFILE.
■ You cannot use JDBC to create a new BFILE.
Example: Reading BFILE Data The following example uses the getBinaryStream()
method of an oracle.sql.BFILE object to read BFILE data into a byte stream
and then read the byte stream into a byte array. The example assumes that the
BFILE has already been opened.
// Read BFILE data from a BFILE locator
Inputstream in = bfile.getBinaryStream();
byte[] byte_array = new byte{10};
int byte_read = in.read(byte_array);
Use the SQL CREATE TABLE statement to create a table containing a BFILE column,
then execute the statement. In this example, the name of the table is
my_bfile_table.
// Create a table containing a BFILE field
cmd = "CREATE TABLE my_bfile_table (x varchar2 (30), b bfile)";
stmt.execute (cmd);
In this example, the VARCHAR2 column designates a row number and the bfile
column stores the locator of the BFILE data.
In this example, the name of the directory alias is test_dir. The locator of the
BFILE file1.data is loaded into the bfile column on row one, and the locator
of the BFILE jdbcTest.data is loaded into the bfile column on row two.
As an alternative, you might want to create the row for the row number and BFILE
locator now, but wait until later to insert the locator. In this case, insert the row
number into the table, and null as a place holder for the BFILE locator.
cmd ="INSERT INTO my_bfile_table VALUES (’three’, null)";
stmt.execute(cmd);
Here, three is inserted into the row number column and null is inserted as the
place holder. Later in your program, insert the BFILE locator into the table by using
a prepared statement.
First get a valid BFILE locator into the bfile object:
rs = stmt.executeQuery("SELECT b FROM my_bfile_table WHERE x=’two’");
rs.next()
oracle.sql.BFILE bfile = ((OracleResultSet)rs).getBFILE(2);
Then, create your prepared statement. Note that because this example uses the
setBFILE() method to identify the BFILE, the prepared statement must be cast to
an OraclePreparedStatement:
OraclePreparedStatement ops =
(OraclePreparedStatement)conn.prepareStatement(INSERT ? INTO my_bfile_table)
WHERE (x = ’three’);
ops.setBFILE(2, bfile);
ops.execute();
Now row two and row three contain the same BFILE.
Once you have the BFILE locators available in a table, you can access and
manipulate the BFILE data. The next section, "Accessing and Manipulating BFILE
Data", describes this.
if (rset.next ())
{
BFILE bfile = ((OracleResultSet)rset).getBFILE (2);
You can select data from the database into Struct objects and create Struct
objects for inserting data into the database. As described in "Class
oracle.sql.STRUCT" on page 4-10, STRUCTs completely preserve data because they
maintain the data in SQL format. Using Struct objects is more efficient and more
precise in these situations where the information does not need to be in a
user-friendly format.
If your code must fully comply with JDBC 2.0, use the functionality in the
oracle.jdbc2.Struct interface:
■ getAttributes(map): retrieves the values from the values array as
java.lang.Object objects; uses entries in the type map (if they have been
defined) to determine the Java classes to use in materializing the data.
■ getAttributes(): retrieves the values of the values array as
java.lang.Object objects
■ getSQLTypeName(): returns a Java String that represents the fully qualified
type name (schema.sql_type_name) of the Oracle object that this Struct
represents
If it is not necessary to comply with JDBC 2.0 and you want to take advantage of the
extended functionality offered by Oracle-defined methods, then cast the output to
oracle.sql.STRUCT.
The oracle.sql.STRUCT class implements the oracle.jdbc2.Struct
interface and provides extended functionality beyond the JDBC 2.0 standard.
Compare the list of methods above with the methods provided for
oracle.sql.STRUCT in "Class oracle.sql.STRUCT" on page 4-10.
((oracle.sql.STRUCT)myStruct).getOracleAttributes()
Adding Entries to an Existing Type Map Follow these general steps to add entries to an
existing type map.
1. Use the getTypeMap() method of your OracleConnection object to return
the connection’s Map object. The getTypeMap() method returns a
java.util.Dictionary object. For example:
java.util.Dictionary myMap = oraconn.getTypeMap();
2. Use the Dictionary object’s put() method to add entries to the map. The
put() method takes two arguments: a SQL type name string and the name of
the Java class object to which you want to map it.
myMap.put(sqlTypeName, classObject);
The sqlTypeName is a string that represents the fully qualified name of the
SQL type in the database. The classObject is the Java class object to which
you want to map the SQL type. Get the class object with the
class.forName() method. You can rewrite the put() method as:
myMap.put(sqlTypeName, class.forName(className));
For example, if you have a PERSON SQL datatype defined in the CORPORATE
database schema, then map it to a Person Java class defined as Person with
this statement:
myMap.put("CORPORATE.PERSON", class.forName("Person"));
The map has an entry that maps the PERSON SQL datatype in the CORPORATE
database to the Person Java class.
3. When you finish adding entries to the map, use the OracleConnection
object’s setTypeMap() method to overwrite the connection’s existing type
map. For example:
oraconn.setTypeMap(myMap);
Creating a New Type Map Follow these general steps to create a new type map.
1. Create an empty map object. An empty map object can be anything that
implements the java.util.Dictionary class. For example, the
java.util.Hashtable class implements the Dictionary class.
2. Use the Map object’s put() method to add entries to the map. For more
information on the put() method, see Step 2 in the preceding section. For
example, if you have an EMPLOYEE SQL type defined in the CORPORATE
database, then you can map it to an Employee class object defined by
Employee.java with this statement:
newMap.put("CORPORATE.EMPLOYEE", class.forName("Employee"));
3. When you finish adding entries to the map, use the OracleConnection
object’s setTypeMap() method to overwrite the connection’s existing type
map. For example:
oraconn.setTypeMap(newMap);
Notes:
■ You can explicitly provide type map objects in some getXXX()
and setXXX() methods to override the custom or default
mapping of your connection.
■ If the type map does not specify a Java class mapping for an
Oracle object type, then it defaults to data from the object type
materialized in Java in an instance of the
oracle.sql.STRUCT class. For more information about this
class, see "Class oracle.sql.STRUCT" on page 4-10.
■ Do not use the type map for inserting custom objects into the
database.
STRUCTS and the Type Map If you do not specify a particular SQL object type in the
type map, then the driver will materialize it as an instance of the
oracle.jdbc2.Struct class. If the SQL object type contains embedded objects,
and they are not present in the type map, the driver will materialize the embedded
objects as instances of oracle.sql.Struct. If the embedded objects are present
in the type map, a call to the getAttributes() method will return embedded
objects as instances of the specified Java classes from the type map.
The JDBC driver calls your readSQL() method to read a stream of data values
from the database and populate an instance of your custom Java class. Typically, the
driver would use this method as part of an OracleResultSet.getObject() call.
Similarly, the JDBC driver calls your writeSQL() method to write a sequence of
data values from an instance of your custom Java class to a stream that can be
written to the database. Typically, the driver would use this method as part of an
OraclePreparedStatement setObject() call.
Understanding the SQLInput and SQLOutput Interfaces The JDBC driver includes classes
that implement the SQLInput and SQLOutput interfaces. It is not necessary to
implement the SQLOutput or SQLInput objects. The JDBC drivers will do this for
you.
The SQLInput implementation is an input stream class, an instance of which must
be passed in to readSQL(). SQLInput includes a readXXX() method for every
possible Java type that attributes of an Oracle object might be converted to, such as
readObject(), readInt(), readLong(), readFloat(), readBlob(), and so
on. Each readXXX() method converts SQL data to Java data and returns it into an
output parameter of the corresponding Java type. For example, readInt() returns
an integer.
The SQLOutput implementation is an output stream class, an instance of which
must be passed in to writeSQL(). SQLOutput includes a writeXXX() method
for each of these Java types. Each writeXXX() method converts Java data to SQL
data, taking as input a parameter of the relevant Java type. For example,
writeString() would take as input a string attribute from your Java class.
Implementing readSQL() and writeSQL() Methods When you create your custom Java
class that implements SQLData, you must also implement the readSQL() and
writeSQL() methods.
You must implement readSQL() as follows:
public void readSQL(SQLInput stream, String sql_type_name) throws SQLException
■ readSQL() must take as input a SQLInput stream and a string that indicates
the SQL type name of the data (in other words, the name of the Oracle object
type, such as EMPLOYEE).
When your Java application calls getObject(), the JDBC driver creates a
SQLInput stream object and populates it with data from the database. The
driver can also determine the SQL type name of the data when it reads it from
the database. When the driver calls readSQL(), it passes in these parameters.
■ For each Java datatype that maps to an attribute of the Oracle object,
readSQL() must call the appropriate readXXX() method of the SQLInput
stream that is passed in.
For example, if you are reading EMPLOYEE objects that have an employee name
as a CHAR variable and an employee number as a NUMBER variable, you must
have a readString() call and a readInt() call in your readSQL() method.
JDBC calls these methods according to the order in which the attributes appear
in the SQL definition of the Oracle object type.
■ readSQL() assigns the data that the readXXX() methods read and convert to
the appropriate fields or elements of your custom Java class.
You must implement writeSQL() as follows:
public void writeSQL(SQLOutput stream) throws SQLException
"Creating Customized Java Classes for Oracle Objects" on page 7-20 contains an
example implementation of the SQLData interface for a given SQL definition of an
Oracle object.
Reading Data from an Oracle Object Using a SQLData Interface This section summarizes
the steps to read data from an Oracle object into your Java application when you
choose the SQLData implementation for your custom Java class.
These steps assume you have already defined the Oracle object type, created the
corresponding custom Java class, updated the type map to define the mapping
between the Oracle object and the Java class, and defined a statement object stmt.
1. Query the database to read the Oracle object into a JDBC result set.
ResultSet rs = stmt.executeQuery("SELECT Emp_col FROM PERSONNEL");
rs.next();
Note that if the type map did not have an entry for the object, getObject()
would return an oracle.sql.STRUCT object. In this case you must cast the
output to an oracle.sql.STRUCT.
Struct empstruct = (oracle.sql.STRUCT)rs.getObject(1);
...
Note: To avoid the need for the type map, use the getSTRUCT()
method. This method always returns a STRUCT object even if there
is a mapping entry in the type map.
3. If you have get methods in your custom Java class, then use them to read data
from your object attributes. For example, if EMPLOYEE has an EmpName
(employee name) of type CHAR and EmpNum (employee number) of type
NUMBER, provide a getEmpName() method that returns a Java String and a
getEmpNum() method that returns an integer (int). Then invoke them in your
Java application as follows:
String empname = emp.getName();
int empnumber = emp.getEmpNum();
Passing SQLData Objects to a Callable Statement as an OUT Parameter Suppose you have
an OracleCallableStatement ocs that calls a PL/SQL function
getEmployee(?). The program passes an employee number (empnumber) to the
function; the function returns the corresponding Employee object.
1. Prepare an OracleCallableStatement to call the getEmployee(?)
function.
OracleCallableStatement ocs =
(OracleCallableStatement) conn.prepareCall("{ ? = call getEmployee(?)
}");
3. Use the getObject() method to retrieve the employee object. Because the
object is returned as a STRUCT, cast the output of getObject() to an
Employee object.
Writing Data to an Oracle Object Using a SQLData Interface This section describes the
steps in writing data to an Oracle object from your Java application when you
choose the SQLData implementation for your custom Java class.
This description assumes you have already defined the Oracle object type, created
the corresponding Java class, and updated the type map to define the mapping
between the Oracle object and the Java class.
1. If you have set methods in your custom Java class, then use them to write data
from Java variables in your application to attributes of your Java datatype
object.
emp.setEmpName(empname);
emp.setEmpNum(empnumber);
This statement uses the emp object and the empname and empnumber variables
defined in "Reading Data from an Oracle Object Using a SQLData Interface" on
page 4-72.
2. Prepare a statement that updates an Oracle object in a row of a database table,
as appropriate, using the data provided in your Java datatype object.
PreparedStatement pstmt = conn.prepareStatement
("INSERT INTO PERSONNEL VALUES (?)");
3. Use the setObject() method of the prepared statement to bind your Java
datatype object to the prepared statement.
pstmt.setObject(1, emp);
Note: You can use your Java datatype objects as either IN or OUT
bind variables.
the custom Java class to your Java application or applet. It takes as input an
oracle.sql.Datum object and an integer indicating the corresponding SQL
type code as specified in the OracleTypes class.
CustomDatum and CustomDatumFactory have the following definitions:
public interface CustomDatum
{
Datum toDatum (OracleConnection conn) throws SQLException;
}
The JDBC drivers provide the following methods to retrieve and insert object data
as instances of CustomDatum.
To retrieve object data:
■ Use the Oracle extension OracleResultSet.getCustomDatum () method:
OracleResultSet.getCustomDatum (int col_index, CustomDatumFactory factory)
This method takes as input the column index of the data in your result set, and
a CustomDatumFactory instance. For example, you can implement a
getFactory() method of your custom Java class to produce the
CustomDatumFactory instance to input to getCustomDatum(). The type
map is not required when using Java classes that implement CustomDatum.
OR
■ Use the standard ResultSet.getObject(index, map) method to retrieve
data as instances of CustomDatum. In this case, you must have an entry in the
type map that identifies the factory class to be used for the given object type,
and its corresponding SQL type name.
This method takes as input the parameter index of the bind variable and the
name of the object containing the variable.
OR
■ Use the standard JDBC PreparedStatement.setObject() method. You
can also use this method, in its various forms, to insert CustomDatum instances
without requiring a type map.
The following sections describe the getCustomDatum() and setCustomDatum()
methods.
To continue the example of an Oracle object EMPLOYEE, you might have something
like the following in your Java application:
CustomDatum datum = ors.getCustomDatum(1, Employee.getFactory());
Notes:
■ CustomDatum and CustomDatumFactory are defined as
separate interfaces so that different Java classes can implement
them if you wish (such as an Employee class and an
EmployeeFactory class).
■ Your custom Java classes must import oracle.sql.* (or at
least CustomDatum, CustomDatumFactory, and Datum),
oracle.jdbc.driver.* (or at least OracleConnection
and OracleTypes), and java.sql.SQLException.
■ Refer to the Javadoc for more information about the
CustomDatum and CustomDatumFactory classes.
oracle.sql.RAW object. This object is then stored in a column of type RAW in the
database.
Support for the CustomDatum interfaces is also highly efficient because the
conversions are designed to work using oracle.sql.* formats, which happen to
be the internal formats used by the JDBC drivers. Moreover, the type map, which is
necessary for the SQLData interface, is not required when using Java classes that
implement CustomDatum. For more information on why classes that implement
CustomDatum do not need a type map, see "Understanding the CustomDatum
Interface" on page 4-75.
Reading Data from an Oracle Object Using the CustomDatum Interface This section
summarizes the steps in reading data from an Oracle object into your Java
application. These steps apply whether you implement CustomDatum manually or
use JPublisher to produce your custom Java classes.
These steps assume you have already defined the Oracle object type, created the
corresponding custom Java class or had JPublisher create it for you, and defined a
statement object stmt.
1. Query the database to read the Oracle object into a result set, casting to an
Oracle result set.
OracleResultSet ors = (OracleResultSet)stmt.executeQuery
("SELECT Emp_col FROM PERSONNEL");
ors.next();
OR
CustomDatum datum = ors.getCustomDatum(1, Employee.getFactory());
This example assumes that Employee is the name of your custom Java class
and ors is the name of your OracleResultSet object.
If you do not want to use getCustomDatum(), the JDBC drivers let you use
the standard JDBC ResultSet.getObject() method to retrieve
CustomDatum data. However, you must have an entry in the type map that
identifies the factory class to be used for the given object type, and its
corresponding SQL type name.
For example, if the SQL type name for your object is EMPLOYEE, then the
corresponding Java class is Employee, which will implement CustomDatum.
The corresponding Factory class is EmployeeFactory, which will implement
CustomDatumFactory.
Use this statement to declare the EmployeeFactory entry for your type map:
map.put ("EMPLOYEE", Class.forName ("EmployeeFactory"));
Then use the form of getObject() where you specify the map object:
Employee emp = (Employee) rs.getObject (1, map);
If the connection’s default type map already has an entry that identifies the
factory class to be used for the given object type, and its corresponding SQL
type name, then you can use this form of getObject():
Employee emp = (Employee) rs.getObject (1);
3. If you have get methods in your custom Java class, use them to read data from
your object attributes into Java variables in your application. For example, if
EMPLOYEE has Name of type CHAR and EmpNum (employee number) of type
NUMBER, provide a getName() method that returns a Java string and a
getEmpNum() method that returns an integer. Then invoke them in your Java
application as follows:
String empname = emp.getName();
int empnumber = emp.getEmpNum();
Writing Data to an Oracle Object Using the CustomDatum Interface This section
summarizes the steps in writing data to an Oracle object from your Java application
when you use JPublisher to produce your custom Java class or otherwise choose the
CustomDatum implementation.
These steps assume you have already defined the Oracle object type, created the
corresponding custom Java class or had JPublisher create it for you.
Note: The type map is not used when you are performing
database INSERTs and UPDATEs.
1. If you have set methods in your custom Java class, then use them to write data
from Java variables in your application to attributes of your Java datatype
object.
emp.setName(empname);
emp.setEmpNum(empnumber);
This statement uses the emp object and the empname and empnumber variables
defined in "Reading Data from an Oracle Object Using the CustomDatum
Interface" on page 4-79.
2. Write an Oracle prepared statement that updates an Oracle object in a row of a
database table, as appropriate, using the data provided in your Java datatype
object.
OraclePreparedStatement opstmt = conn.prepareStatement
("UPDATE PERSONNEL SET Employee = ? WHERE Employee.EmpNum = 28959);
Note: You can use your Java datatype objects as either IN or OUT
bind variables.
The ADDRESS object type has two attributes: a street name and a house number. The
PEOPLE table has three columns: a column for character data, a column for numeric
data, and a column containing a reference to an ADDRESS object.
To retrieve an object reference, follow these general steps:
1. Use a standard SQL SELECT statement to retrieve the reference from a database
table REF column.
2. Use getREF() to get the address reference from the result set into a REF object.
3. Let Address be the Java custom class corresponding to the SQL object type
ADDRESS.
4. Add the correspondence between the Java class Address and the SQL type
ADDRESS to your type map.
5. Use the getValue() method to retrieve the contents of the Address reference.
Cast the output to a Java Address object.
Here is the code for these three steps, where stmt is a previously defined statement
object. The PEOPLE database table is defined earlier in this section:
ResultSet rs = stmt.executeQuery("SELECT col3 FROM PEOPLE");
rs.next();
REF ref = rs.getREF(1);
Address a = (Address)(ref.getValue());
As with other SQL types, you could retrieve the reference with the getObject()
method of your result set. Note that this would require you to cast the output. For
example:
REF ref = (REF)rs.getObject(1);
where param_index is the parameter index and sql_type is the SQL type
code (in this case, OracleTypes.REF). The sql_type_name is the name of
the STRUCT to which this object reference points. For example, if the OUT
parameter is a REF to an ADDRESS object (as in the previous section), then
ADDRESS is the sql_type_name that should be passed in.
3. Execute the call:
ocs.execute()
Arrays include varrays (variable-length arrays) and nested tables. The methods in
the oracle.sql.ARRAY class enable you to access and manipulate the array and
its data even if it is a varray or nested table. That is, you do not have to add any
special code when you are accessing a varray or nested table. The methods can
determine if they are being applied to a varray or nested table, and respond by
taking the appropriate actions.
Oracle supports only named arrays, where you specify a SQL type name to describe
a type of array. The SQL type name is assigned to the array when you create it, as in
the following SQL syntax:
CREATE TYPE <sql_type_name> AS <datatype>
the varray. You must specify a maximum size when you declare the array type.
For example:
CREATE TYPE myNumType AS VARRAY(10) OF NUMBER;
This statement defines myNumType as a SQL type name that describes a varray of
NUMBERs that can contain no more than 10-elements.
A nested table is an unordered set of data elements, all of the same datatype. It has
a single column, and the type of that column is a built-in type or an object type. If
the table is an object type, it can also be viewed as a multi-column table, with a
column for each attribute of the object type. Create a nested table with this SQL
syntax:
CREATE TYPE myNumList AS TABLE OF integer;
This statement identifies myNumList as a SQL type name that defines the table type
used for the nested tables of the type integer.
The remainder of this section describes how to access and update array data. For
general information about the oracle.sql.ARRAY class, including how to
manually create array objects, see "Class oracle.sql.ARRAY" on page 4-14. For a
complete code example of creating a table with an array column, then manipulating
and printing the contents, see "Array Sample" on page 7-16.
Oracle provides versions of these methods that enable you to specify a type map so
you can choose how you want your SQL datatypes to map to Java datatypes. Oracle
also provides methods that enable you to retrieve all of an array’s elements or a
subset of the array (but note, there is no performance advantage in retrieving a
subset of an array as opposed to retrieving the entire array).
getArray() Method: The getArray() method retrieves the element values of the
array into a java.lang.Object[] array. The elements are converted to the Java
types corresponding to the SQL type of the data in the original array.
The getArray() materializes the data as an array of oracle.sql.* objects and
does not use a type map. Oracle also provides a getArray(map) method to let you
specify a type map and a getArray(index,count) method to retrieve a subset
of the array.
Oracle recommends that you use getResultSet() when getting data from nested
tables. Nested tables can have an unlimited number of elements. The ResultSet
object returned by the method initially points at the first row of data. You get the
contents of the nested table by using the next() method and the appropriate
getXXX() method. In contrast, getArray() returns the entire contents of the
nested table at one time.
The getResultSet() method uses the connection’s default type map to
determine the mapping between the SQL type of the Oracle object and its
corresponding Java datatype. If you do not want to use the connection’s default
type map, another version of the method, getResultSet(map), enables you to
specify an alternate type map.
Oracle also provides the getResultSet(index,count) and
getResultSet(index,count,map) methods to retrieve a subset of the array.
In this case, the result set contains one row for each array element, with two
columns in each row. The first column stores the index into the array; the second
column stores the BigDecimal element value.
default mapping. This is because these methods use the connection’s default type
map to determine the mapping.
However, if you do not want default behavior, then you can use the
getArray(map) or getResultSet(map) method to specify a type map that
contains alternate mappings. If there are entries in the type map corresponding to
the Oracle objects in the array, then each object in the array is mapped to the
corresponding Java type specified in the type map. For example:
Object[] object = (Object[])objArray.getArray(map);
Example: Getting and Printing an Array of Primitive Datatypes from a Result Set The
following example assumes that a connection object conn and a statement object
stmt have already been created. In the example, an array with the SQL type name
num_array is created to store a varray of NUMBER data. The num_array is in turn
stored in a table varray_table.
A query selects the contents of the varray_table. The result set is cast to an
OracleResultSet object; getARRAY() is applied to it to retrieve the array data
into my_array, which is an object of type oracle.sql.ARRAY.
Because my_array is of type oracle.sql.ARRAY, you can apply the methods
getSQLTypeName() and getBaseType() to it to return the name of the SQL type
of each element in the array and its integer code.
The program then prints the contents of the array. Because the contents of
my_array are of the SQL datatype NUMBER, it must first be cast to the BigDecimal
datatype. In the for loop, the individual values of the array are cast to
BigDecimal and printed to standard output.
stmt.execute ("CREATE TYPE num_varray AS VARRAY(10) OF NUMBER(12, 2)");
stmt.execute ("CREATE TABLE varray_table (col1 num_varray)");
stmt.execute ("INSERT INTO varray_table VALUES (num_varray(100, 200))");
Note that if you use getResultSet() to obtain the array, you would first get the
result set object, then use the next() method to iterate through it. Notice the use of
the parameter indexes in the getInt() method to retrieve the element index and
the element value.
ResultSet rset = my_array.getResultSet();
while (rset.next())
{
// The first column contains the element index and the
// second column contains the element value
System.out.println(">> index " + rset.getInt(1)+" = " + rset.getInt(2));
};
where param_index is the parameter index, sql_type is the SQL type code,
and sql_type_name is the name of the array type. In this case, the sql_type
is OracleTypes.ARRAY.
3. Execute the query:
ocs.executeQuery()
map or if the type map does not contain an entry for a particular Oracle object, then
the element is returned as an oracle.sql.STRUCT.
If you want the type map to determine the mapping between the Oracle objects in
the array and their associated Java classes, then you must add them to the type map
if they are not already there. For instructions on how to add entries to an existing
type map or how to create a new type map, see "Understanding Type Maps" on
page 4-66.
The following example illustrates how you can use a type map to map the elements
of an array to a custom Java object class. In this case, the array is a nested table. The
example begins by defining an EMPLOYEE object that has a name attribute and
employee number attribute. EMPLOYEE_LIST is a nested table type of EMPLOYEE
objects. Then an EMPLOYEE_TABLE is created to store the names of departments
within a corporation and the employees associated with each department. In the
EMPLOYEE_TABLE, the employees are stored in the form of EMPLOYEE_LIST
tables.
stmt.execute("CREATE TYPE EMPLOYEE AS OBJECT(EmpName VARCHAR2(50),EmpNo
INTEGER))");
If you want to select all of the employees belonging to the SALES department as the
custom Java object EmployeeObj, then you must create a mapping in the type map
between the EMPLOYEE SQL type and the EmployeeObj custom Java object class.
To do this, first create your statement and result set objects, then select the
EMPLOYEE_LIST associated with the SALES department into the result set. Cast the
result set to OracleResultSet so that the getARRAY() method can retrieve the
EMPLOYEE_LIST object into the employeeArray object.
Statement s = conn.createStatement();
OracleResultSet rs = (OracleResultSet)
s.executeQuery("SELECT Employees FROM employee_table
WHERE DeptName = ’SALES’");
Now that you have the EMPLOYEE_LIST object, get the existing type map and add
an entry that maps the EMPLOYEE SQL type to the EmployeeObj Java type.
// add type map entry to map SQL type
// "EMPLOYEE" to Java type "EmployeeObj"
Dictionary map = conn.getTypeMap();
map.put("EMPLOYEE", Class.forName("EmployeeObj"));
Retrieve the SQL EMPLOYEE objects from the EMPLOYEE_LIST. To do this, apply
the getArray() method of the oracle.jdbc2.Array class to employeeArray.
This method returns an array of objects. The getArray() method returns the
EMPLOYEE objects into the employees object array.
// Retrieve array elements
Object[] employees = (Object[]) employeeArray.getArray();
Finally, create a loop to assign each of the EMPLOYEE SQL objects to the
EmployeeObj Java object emp.
// Each array element is mapped to EmployeeObj object.
for (int i=0; i<employees.length; i++)
{
EmployeeObj emp = (EmployeeObj) employees[i];
...
}
Performance Extensions
Oracle JDBC drivers support these extensions that improve performance by
reducing round trips to the database:
■ Prefetching rows reduces round trips to the database by fetching multiple rows
of data each time data is fetched; the extra data is stored in client-side buffers
for later access by the client. The number of rows to prefetch can be set as
desired.
■ Batching updates also reduces round trips to the database, saving on the client
side a number of updates that are to be made, and then going to the database
once to execute all the updates.
■ Specifying column types gets around an inefficiency in the usual JDBC protocol
for performing and returning the results of queries.
■ Suppressing database metadata TABLE_REMARKS columns avoids an expensive
outer join operation.
Oracle supports several extensions to connection properties objects to support these
performance extensions. The properties object extensions enable you to set the
remarksReporting flag and default values for prefetching and update-batching.
For more information, see "Oracle Extensions for Connection Properties" on
page 4-109.
Row Prefetching
Oracle JDBC drivers allow you to set the number of rows to prefetch into the client
while a result set is being populated during a query. This feature reduces the
number of round trips to the server.
Standard JDBC receives the result set one row at a time, and each row requires a
round trip to the database. The row prefetching feature associates an integer
row-prefetch setting with a given statement object. JDBC fetches that number of
rows at a time from the database during the query. That is, JDBC will fetch N rows
that match the query criteria and bring them all back to the client at once, where N
is the prefetch setting. Then, once your next() calls have run through those N
rows, JDBC will go back to fetch the next N rows that match the criteria.
You can set the number of rows to prefetch for a particular Oracle statement (any
type of statement). You can also reset the default number of rows that will be
prefetched for all statements in your connection. The default number of rows to
prefetch to the client is 10.
Set the number of rows to prefetch for a particular statement as follows:
1. Cast your statement object to an OracleStatement,
OraclePreparedStatement, or OracleCallableStatement object, as
applicable, if it is not already one of these.
2. Use the setRowPrefetch() method of the statement object to specify the
number of rows to prefetch, passing in the number as an integer. If you want to
check the current prefetch number, use the getRowPrefetch() method of the
Statement object, which returns an integer.
Set the default number of rows to prefetch for all statements in a connection as
follows:
1. Cast your Connection object to an OracleConnection object.
2. Use the setDefaultRowPrefetch() method of your OracleConnection
object to set the default number of rows to prefetch, passing in an integer that
specifies the desired default. If you want to check the current setting of the
default, then use the getDefaultRowPrefetch() method of the
OracleConnection object. This method returns an integer.
A statement object receives the default row prefetch setting from the associated
connection at the time the statement object is created. Subsequent changes to the
connection’s default row prefetch setting have no effect on the statement’s row
prefetch setting.
If a column of a result set is of datatype LONG or LONG RAW (that is, the streaming
types), JDBC changes the statement’s row prefetch setting to 1, even if you never
actually read a value of either of those types.
If you use the form of the DriverManager class getConnection() method that
takes a Properties object as an argument, then you can set the connection’s
default row prefetch value that way. See "Specifying a Database URL and Properties
Object" on page 3-6 and "Oracle Extensions for Connection Properties" on
page 4-109 for more information about the Properties object and connection
properties.
Example: Row Prefetching The following example illustrates the row prefetching
feature. It assumes you have imported the oracle.jdbc.driver.* classes.
Connection conn =
DriverManager.getConnection("jdbc:oracle:oci8:","scott","tiger");
/* The following statement gets the default row prefetch value for
the connection, that is, 7.
*/
Statement stmt = conn.createStatement();
while( rset.next () )
System.out.println( rset.getString (1) );
while( rset.next() )
System.out.println( rset.getString (1) );
stmt.close();
Setting Update Batch Value for Individual Statements You can set the batch value for any
individual Oracle prepared statement by applying it to the
OraclePreparedStatement object. The batch value that you set for an
individual statement overrides the value set for the connection. You can also set a
default batch value that will apply to any Oracle prepared statement in your Oracle
connection by applying it to the OracleConnection object.
Follow these steps to apply the Oracle batch value feature for a particular prepared
statement:
1. Write your prepared statement and specify input values for the first row:
PreparedStatement ps = conn.prepareStatement ("INSERT INTO dept VALUES
(?,?,?)");
ps.setInt (1,12);
ps.setString (2,"Oracle");
ps.setString (3,"USA");
3. If you send an execute update statement to the database at this point, then no
data will be sent to the database. Instead, a call to executeUpdate() will
return 0.
// No data is sent to the database by this call to executeUpdate
System.out.println ("Number of rows updated so far: "
+ ps.executeUpdate ());
4. If you enter a set of input values for a second row and an execute update, then
the number of batch calls to executeUpdate() will be equal to the batch
value of 2. The data will be sent to the database and both rows will be inserted
in a single round trip.
ps.setInt (1, 11);
ps.setString (2, "Applications");
ps.setString (3, "Indonesia");
ps.close ();
Overriding the Default Batch Update Value If you want to execute accumulated
statements before the batch value is reached, then use the sendBatch() method of
the OraclePreparedStatement object. For example:
1. Cast your connection to an OracleConnection object and apply the
setDefaultExecuteBatch() method for the connection. This example sets
the default batch for all statements in the connection to 50.
((OracleConnection)conn).setDefaultExecuteBatch (50);
2. Write your prepared statement and specify input values for the first row as
usual, then execute the statement:
PreparedStatement ps =
conn.prepareStatement ("insert into dept values (?, ?, ?)");
The execute update does not happen at this point. The ps.executeUpdate()
method returns "0".
3. If you enter a set of input values for a second row and an executeUpdate(),
the data will still not be sent to the database since the batch default value for the
statement is the same as for the connection: 50.
ps.setInt (1, 33);
ps.setString (2, "Applications");
ps.setString (3, "Indonesia");
4. If you apply the sendBatch() method at this point, then the two previously
batched executes will be sent to the database in a single round trip. The
sendBatch() method also returns the number of updated rows. This property
of sendBatch() is used by println to print the number of updated rows.
// Execution of both previously batched executes will happen
// at this point. The number of rows updated will be
// returned by sendBatch.
rows = ((OraclePreparedStatement)ps).sendBatch ();
ps.close ();
Setting Update Batch Value for the Connection You can specify a default batch value for
any Oracle prepared statement in your Oracle connection. To do this, set the
setDefaultExecute() method on the OracleConnection object. For example,
the following statement sets the default batch value for all prepared statements
belonging to the conn connection object to 20:
((OracleConnection)conn).setDefaultExecuteBatch(20);
Even though this sets the default batch value for all of the prepared statements
belonging to the connection, you can override it by calling setDefaultBatch()
on individual statements.
Checking Batch Value The getExecuteBatch() method enables you to check the
current setting of the default batch value for a specific Oracle prepared statement
object or for all of the prepared statements that belong to the Oracle connection. For
example:
Integer batch_val = ((OraclePreparedStatement)ps).getExecuteBatch();
OR
Integer batch_val = ((OracleConnection)conn).getDefaultExecuteBatch();
Example: Update Batching The following example illustrates how you use the Oracle
update batching feature. It assumes you have imported the
oracle.jdbc.driver.* classes.
Connection conn =
DriverManager.getConnection("jdbc:oracle:oci8:","scott","tiger");
PreparedStatement ps =
conn.prepareStatement("insert into dept values (?, ?, ?)");
ps.setInt(1, 23);
ps.setString(2, "Sales");
ps.setString(3, "USA");
ps.executeUpdate(); //JDBC queues this for later execution
ps.setInt(1, 24);
ps.setString(2, "Blue Sky");
ps.setString(3, "Montana");
ps.executeUpdate(); //JDBC queues this for later execution
ps.setInt(1, 25);
ps.setString(2, "Applications");
ps.setString(3, "India");
ps.executeUpdate(); //The queue size equals the batch value of 3
//JDBC sends the requests to the database
ps.setInt(1, 26);
ps.setString(2, "HR");
ps.setString(3, "Mongolia");
ps.executeUpdate(); //JDBC queues this for later execution
((OraclePreparedStatement)ps).sendBatch();
//JDBC sends the queued request
ps.close();
Notes:
■ Each statement has its own batch count. Only executes on a
particular statement add to the batch count.
■ Updates deferred through batching can affect the results of
other queries. In the following example, if the first query is
deferred due to batching, then the second will return
unexpected results:
UPDATE emp SET name = "Sue" WHERE name = "Bob";
SELECT name FROM emp WHERE name = "Sue";
Redefining Column Types Limitations To use this feature, you must specify a datatype
for each column of the expected result set. If the number of columns for which you
specify types does not match the number of columns in the result set, the process
fails with a SQLException.
You cannot define column types for objects or object references.
Redefining Column Types for a Query Following these general steps to redefine column
types for a query:
1. Cast your statement object to an OracleStatement,
OraclePreparedStatement, or OracleCallableStatement object, as
applicable, if it is not already one of these.
2. If necessary, use the clearDefines() method of your Statement object to
clear any previous column definitions for this Statement object.
3. Determine the following for each column of the expected result set:
■ column index (position)
■ code for the type of the expected return data (which can differ from the
column type)
This is according to oracle.jdbc.driver.OracleTypes for
Oracle-specific types, and according to either java.sql.Types or
OracleTypes for standard types (constants for standard types have the
same value in Types and OracleTypes).
4. For each column of the expected result set, invoke the defineColumnType(),
method of your Statement object, passing it these parameters:
■ column index (integer)
■ type code (integer)
Use the static constants of the java.sql.Types class or, for
Oracle-specific types, the static constants of the
oracle.jdbc.driver.OracleTypes class (such as Types.INTEGER,
Types.FLOAT, Types.VARCHAR, OracleTypes.VARCHAR, and
OracleTypes.ROWID.).
■ (optionally) maximum field size (integer)
For example, assuming stmt is an Oracle statement, use this syntax:
stmt.defineColumnType(column_index, type);
OR
stmt.defineColumnType(column_index, type, max_size);
Set maximum field size if you do not want to receive the full default length of
the data. Less data than this maximum size will be returned if the maximum
field size is set to a smaller value using the setMaxFieldSize() method of
the standard JDBC Statement class, or if the natural maximum size of the
datatype is smaller. Specifically, the size of the data returned will be the
minimum of:
– the maximum field size set in defineColumnType() or
– the maximum field size set in setMaxFieldSize() or
– the natural maximum size of the datatype
Once you complete these steps, use the statement’s executeQuery() method to
perform the query.
Example: Defining Column Types The following example illustrates the use of this
feature. It assumes you have imported the oracle.jdbc.driver.* classes.
Connection conn =
DriverManager.getConnection("jdbc:oracle:oci8:","scott","tiger");
while (rset.next() )
System.out.println(rset.getString(1));
stmt.close();
As this example shows, you must cast the statement (stmt) to type
OracleStatement in the invocation of the defineColumnType() method. The
connection’s createStatement() method returns an object of type
java.sql.Statement, which does not have the defineColumnType() and
clearDefines() methods. These methods are provided only in the
OracleStatement implementation.
The define-extensions use JDBC types to specify the desired types. The allowed
define types for columns depend on the internal Oracle type of the column.
All columns can be defined to their "natural" JDBC types; in most cases, they can be
defined to Types.CHAR or Types.VARCHAR.
Table 4–6 lists the valid column definition arguments you can use in the
defineColumnType() method.
applies both on input (the catalog parameter) and output (the catalog
column in the returned ResultSet). On input, the construct " " (the empty
string) retrieves procedures and arguments without a package, that is,
stand-alone objects. A null value means to drop from the selection criteria, that
is, return information about both stand-alone and packaged objects (same as
passing in "%"). Otherwise the catalog parameter should be a package name
pattern (with SQL wild cards, if desired).
■ schemaPattern: All objects within Oracle must have a schema, so it does not
make sense to return information for those objects without one. Thus, the
construct " " (the empty string) is interpreted on input to mean the objects in
the current schema (that is, the one to which you are currently connected). To be
consistent with the behavior of the catalog parameter, null is interpreted to
drop the schema from the selection criteria (same as passing in "%"). It can also
be used as a pattern with SQL wild cards.
■ procedureNamePattern and columnNamePattern: The empty string (" ")
does not make sense for either parameter, because all procedures and
arguments must have names. Thus, the construct " " will raise an exception. To
be consistent with the behavior of other parameters, null has the same effect as
passing in "%".
In addition to the URL, you use an object of the standard Java Properties class as
input. For example:
java.util.Properties info = new java.util.Properties();
info.put ("user", "scott");
info.put ("password","tiger");
getConnection ("jdbc:oracle:oci8:",info);
Table 4–7 lists the connection properties that Oracle JDBC drivers support,
including the Oracle extensions for defaultRowPrefetch, remarksReporting,
and defaultBatchValue.
Notes:
■ The oracle.sql.ROWID class replaces
oracle.jdbc.driver.ROWID, which was used in previous
releases of Oracle JDBC.
■ Refer to the Javadoc for information about features of the
ROWID class.
Example: ROWID The following example shows how to access and manipulate ROWID
data.
Statement stmt = conn.createStatement();
// Query the employee names with "FOR UPDATE" to lock the rows.
// Select the ROWID to identify the rows to be updated.
ResultSet rset =
stmt.executeQuery ("SELECT ename, rowid FROM emp FOR UPDATE");
PreparedStatement pstmt =
conn.prepareStatement ("UPDATE emp SET ename = ? WHERE rowid = ?");
1. Use a JDBC callable statement to call a stored procedure (it must be a callable
statement as opposed to a prepared statement because there is an output
parameter).
2. The stored procedure returns a REF CURSOR.
3. The Java application casts the callable statement to an Oracle callable statement
and uses the getCursor() method of the OracleCallableStatement class
to materialize the REF CURSOR as a JDBC ResultSet object.
4. The result set is processed as requested.
Example: Accessing REF CURSOR Data This example shows how to access REF
CURSOR data.
import oracle.jdbc.driver.*;
...
CallableStatement cstmt;
ResultSet cursor;
cstmt.registerOutParameter(1, OracleTypes.CURSOR);
cstmt.execute();
cursor = ((OracleCallableStatement)cstmt).getCursor(1);
CursorName
Oracle JDBC drivers do not support the getCursorName() and
setCursorName() methods because there is no convenient way to map them to
Oracle constructs. Oracle recommends using ROWID instead. For more information
on how to use and manipulate ROWIDs, see "Oracle ROWID Type" on page 4-111.
Read-Only Connection
The read-only connection is not supported. There is no Oracle equivalent to the
read-only connection.
SQLWarning Class
The java.sql.SQLWarning class provides information on a database access
warning. Warnings typically contain a description of the warning and a code that
identifies the warning. Warnings are silently chained to the object whose method
caused it to be reported. The Oracle JDBC drivers do not support SQLWarning.
For information on how the Oracle JDBC drivers handle errors, see "Error Messages
and JDBC" on page 3-25.
Bind by Name
Bind by name is not supported. Under certain circumstances previous versions of
the Oracle JDBC drivers have allowed binding statement variables by name. In the
following statement, the named variable EmpId would be bound to the integer
314159.
PreparedStatement p = conn.prepareStatement("SELECT name FROM EMP
WHERE id = :EmpId");
p.setInt(1, 314159);
The capability is not part of the JDBC specification, either 1.0 or 2.0, and Oracle does
not support it. The JDBC drivers can throw a SQLException or produce
unexpected results.
Prior releases of the Oracle JDBC drivers did not retain bound values from one call
of execute to the next as specified in JDBC 1.0. Bound values are now retained. For
example:
PreparedStatement p = conn.prepareStatement("SELECT name FROM EMP
WHERE id = :? AND dept = :?");
p.setInt(1, 314159);
p.setString(2, "SALES");
ResultSet r1 = p.execute();
p.setInt(1, 425260);
ResultSet r2 = p.execute();
Using NLS
This section contains these subsections:
■ How JDBC Drivers Perform NLS Conversions
■ NLS Restrictions
Oracle’s JDBC drivers support NLS (National Language Support). NLS lets you
retrieve data or insert data into a database in any character set that Oracle supports.
If the clients and the server use different character sets, the driver provides the
support to perform the conversions between the database character set and the
client character set.
For more information on NLS, NLS environment variables, and the character sets
that Oracle supports, see the Oracle8i National Language Support Guide. See the
Oracle8i Reference for more information on the database character set and how it is
created.
Here are a few examples of commonly used Java methods for JDBC that rely heavily
on NLS character set conversion:
■ java.sql.ResultSet methods getString() and getUnicodeStream()
return values from the database as Java strings and as a stream of Unicode
characters, respectively.
■ oracle.sql.CLOB method getCharacterStream() returns the contents of
a CLOB as a Unicode stream.
■ oracle.sql.CHAR methods getString(), toString(), and
getStringWithReplacement() convert the following data to strings:
– getString(): converts the sequence of characters represented by the
CHAR object to a string and returns a Java String object.
– toString(): identical to getString(), but if the character set is not
recognized, toString() returns a hexadecimal representation of the CHAR
data.
– getStringWithReplacement(): identical to getString(), except
characters that have no Unicode representation in the character set of this
CHAR object are replaced by a default replacement character.
where the database uses the US7ASCII or WE8ISO8859P1 character set. In this
case, the driver converts the data directly from the database character set to UCS-2
which is used in Java applications.
If you are working with databases that employ a non-US7ASCII or
non-WE8ISO8859P1 character set (for example, Japanese or Korean), then the
driver converts the data, first to UTF-8, then to UCS-2. For example, the driver
always converts CHAR and VARCHAR2 data in a non-US7ASCII,
non-WE8ISO8859P1 character set. It does not convert RAW data.
Notes:
■ The driver sets the value of NLS_LANG to UTF-8 to minimize
the number of conversions it performs in Java. It performs the
conversion from database character set to UTF-8 in C.
■ The change to UTF-8 is for the JDBC application process only.
■ For more information on the NLS_LANG parameter, see the
Oracle8i National Language Support Guide.
Note: The OCI and Thin drivers both provide the same
transparent support for NLS.
NLS Restrictions
Table 5–1 New Restricted Maximum Bind Length for Client-Side Drivers
Server Old Max Bind
Driver Version Datatype Length (bytes) New Restricted Max Bind Length (bytes)
Thin and OCI V8 CHAR 2000 min(2000,4000 / NLS_Ratio)
VARCHAR2 4000 (4000 / NLS_Ratio)
For example, when connecting to an Oracle8 server, you cannot bind more than:
■ min (2000, 4000 / NLS_RATIO) for CHAR types
OR
■ 4000 / NLS_RATIO for VARCHAR2 types
Table 5–2 contains examples of the NLS Ratio and maximum bind values for some
common server character sets.
Table 5–2 NLS Ratio and Size Limits for Common Server Character Sets
Maximum Bind Value on
Server Character Set NLS Ratio Oracle8 Server (in bytes)
WE8DEC 1 4000
Table 5–2 NLS Ratio and Size Limits for Common Server Character Sets (Cont.)
Maximum Bind Value on
Server Character Set NLS Ratio Oracle8 Server (in bytes)
US7ASCII 1 4000
ISO 8859-1 through 10 1 4000
JA16SJIS 2 2000
JA16EUC 3 1333
Coding Applets
Except for importing the JDBC interfaces to access JDBC entry points, you write a
JDBC applet like any other Java applet. Depending on whether you are coding your
applet for a JDK 1.1.1 browser or a JDK 1.0.2 browser, there are slight differences in
the code that you use. In both cases, your applet must use the JDBC Thin driver,
which connects to the database with TCP/IP protocol.
If you are targeting a JDK 1.1.1 browser (such as Netscape 4.x or Internet Explorer
4.x), then you must:
■ import the java.sql package into your program. The java.sql package
contains the standard JDBC 1.22 interfaces and is part of the standard JDK 1.1.1
class library.
■ register the driver with the oracle.jdbc.driver.OracleDriver() class
and specify the driver name in the connect string as thin.
If you are targeting a JDK 1.0.2 browser (such as Netscape 3.x or Internet Explorer
3.x), then you must:
■ import the jdbc.sql package into your program.
The jdbc.sql package is not a part of the standard JDK 1.0.2 class library. It is
a separate library that you download as part of the JDBC distribution. The
jdbc.sql package was created because JDK 1.0.2 browsers do not allow
packages starting with the string "java" to be downloaded. As a work-around,
the java.sql package has been renamed to jdbc.sql. This renamed package
is shipped with the Oracle JDBC product.
■ register the driver with the oracle.jdbc.dnlddriver.OracleDriver()
class and specify the driver name in the connect string as dnldthin.
The following sections illustrate the differences in coding an applet for a JDK 1.1.1
browser compared with a JDK 1.0.2 browser.
■ Coding Applets for a JDK 1.1.1 Browser
■ Coding Applets for a JDK 1.0.2 Browser
In this example, the connect string contains the username and password, but you
can also pass them as arguments to getConnection() after obtaining them from
the user. For more information on connecting to the database, see "Opening a
Connection to a Database" on page 3-3.
import jdbc.sql.*;
public class JdbcApplet extends java.applet.Applet
{
Connection conn; // Hold the connection to the database
public void init ()
{
// Register the driver
DriverManager.registerDriver (new oracle.jdbc.dnlddriver.OracleDriver());
// Connect to the database
conn = DriverManager.getConnection
("jdbc:oracle:dnldthin:scott/[email protected]:1521:orcl");
...
}
}
This section begins with describing the most simple case, connecting to a database
on the same host from which the applet was downloaded (that is, the same host as
the web server). It then describes the two different ways in which you can connect
to a database running on a different host.
If you use the TNS keyword-value pair to specify the connection information to the
JDBC Thin driver, then you must declare the protocol as TCP.
uses the JDBC Thin driver can connect to a Connection Manager running on the
web server host and have the Connection Manager redirect the Net8 packets to an
Oracle server running on a different host.
Figure 5–1 illustrates the relationship between the applet, the Oracle8 Connection
Manager, and the database.
Net8 Listener
CMAN
applet
in browser any Net8
TCP/IP web server protocol
(only)
webHost oraHost
Using the Oracle8 Connection Manager requires two steps that are described in
these sections:
■ Installing and Running the Oracle8 Connection Manager
■ Writing the Connect String that Targets the Oracle8 Connection Manager
Installing and Running the Oracle8 Connection Manager You must install the Connection
Manager on the web server host. You install it from the Oracle8 distribution media.
Please refer to the Net8 Administrator’s Guide if you need more help to install the
Connection Manager.
On the web server host you must create a CMAN.ORA file in the
[ORACLE_HOME]/NET8/ADMIN directory. The options you can declare in a
CMAN.ORA file include firewall and connection pooling support. Please refer to the
Net8 Administrator’s Guide for more information on the options you can enter in a
CMAN.ORA file.
Here is an example of a very simple CMAN.ORA file. Replace <web-server-host> with
the name of your web server host. The fourth line in the file indicates that the
connection manager is listening on port 1610. You must use this port number in
your connect string for JDBC.
cman = (ADDRESS_LIST =
(ADDRESS = (PROTOCOL=TCP)
(HOST=<web-server-host>)
(PORT=1610)))
cman_profile = (parameter_list =
(MAXIMUM_RELAYS=512)
(LOG_LEVEL=1)
(TRACING=YES)
(RELAY_STATISTICS=YES)
(SHOW_TNS_INFO=YES)
(USE_ASYNC_CALL=YES)
(AUTHENTICATION_LEVEL=0)
)
Note that the Java Net8 version inside the JDBC Thin driver does not have
authentication service support. This means that the AUTHENTICATION_LEVEL
configuration parameter in the CMAN.ORA file must be set to 0.
You can find a description of the options listed in the CMAN.ORA file in the Net8
Administrator’s Guide.
After you create the file, start the Oracle8 Connection Manager at the operating
system prompt with this command:
cmctl start
To use your applet, you must now write the connect string for it.
Writing the Connect String that Targets the Oracle8 Connection Manager This section
describes how to write the connect string in your applet so that the applet connects
to the Connection Manager, and the Connection Manager connects with the
database. In the connect string, you specify an address list that lists the protocol,
port, and name of the web server host on which the Connection Manager is
running, followed by the protocol, port, and name of the host on which the
database is running.
The following example describes the situation illustrated in Figure 5–1. The web
sever on which the Connection Manager is running is on host webHost and is
listening on port 1610. The database to which you want to connect is running on
host oraHost, listening on port 1521, and SID ORCL. You write the connect string
in TNS keyword-value format:
Connection conn =
DriverManager.getConnection ("jdbc:oracle:thin:" +
"@(description=(address_list=" +
"(address=(protocol=tcp)(host=webHost)(port=1610))" +
"(address=(protocol=tcp)(host=oraHost)(port=1521)))" +
"(source_route=yes)" +
"(connect_data=(sid=orcl)))", "scott", "tiger");
The first element in the address_list entry represents the connection to the
Connection Manager. The second element represents the database to which you
want to connect. The order in which you list the addresses is important.
Notice that you can also write the same connect string in this format:
String connString =
"jdbc:oracle:thin:@(description=(address_list=
(address=(protocol=tcp)(port=1610)(host=webHost))
(address=(protocol=tcp)(port=1521)(host=oraHost)))
(connect_data=(sid=orcl))
(source_route=yes))";
Connection conn = DriverManager.getConnection(connString, "scott", "tiger");
When your applet uses a connect string such as the one above, it will behave exactly
as if it were connected directly to the database on the host oraHost.
For more information on the parameters that you specify in the connect string, see
the Net8 Administrator’s Guide.
Connecting through Multiple Connection Managers Your applet can reach its target
database even if it first has to go through multiple Connection Managers (for
example, if the Connection Managers form a "proxy chain"). To do this, add the
addresses of the Connection Managers to the address list, in the order that you plan
to access them. The database listener should be the last address on this list. See the
Net8 Administrator’s Guide for more information about source_route addressing.
2. Include applet code that asks for appropriate permission before opening a
socket.
If you are using Netscape, then your code would include a statement like this:
netscape.security.PrivilegeManager.enablePrivilege("UniversalConnect");
Connection conn = DriverManager.getConnection(...);
For more information on writing applet code that asks for permissions, see
Netscape’s Introduction to Capabilities Classes at:
http://developer.netscape.com/docs/manuals/signedobj/capabilities/contents.htm
Configuring a Firewall for Applets that use the JDBC Thin Driver
The instructions in this section assume that you are running a Net8-compliant
firewall.
Java applets do not have access to the local system (that is, they cannot get the
hostname locally or environment variables) because of security limitations. As a
result, the JDBC Thin driver cannot access the hostname on which it is running. The
firewall cannot be provided with the hostname. To allow requests from JDBC Thin
clients to go through the firewall, you must do the following two things to the
firewall’s list of rules:
■ Add the IP address (not the hostname) of the host on which the JDBC applet is
running.
■ Ensure that the hostname "__jdbc__" never appears in the firewall’s rules.
This hostname has been hard-coded as a bogus hostname inside the driver to
force an IP address lookup. If you do enter this hostname in the list of rules,
then every applet using Oracle's JDBC Thin driver will be able to go through
your firewall.
By not including the Thin driver’s hostname, the firewall is forced to do an IP
address lookup and base its access decision on the IP address and not on the
hostname.
The first element in the address_list represents the connection to the firewall.
The second element represents the database to which you want to connect. Note
that the order in which you specify the addresses is important.
Notice that you can also write the preceding connect string in this format:
String connString =
"jdbc:oracle:thin:@(description=(address_list=
(address=(protocol=tcp)(port=1600)(host=fireWallHost))
(address=(protocol=tcp)(port=1521)(host=oraHost)))
(connect_data=(sid=orcl))
(source_route=yes))";
Connection conn = DriverManager.getConnection(connString, "scott", "tiger");
When your applet uses a connect string similar to the one above, it will behave as if
it were connected to the database on host oraHost.
For more information on the parameters used in the above example, see the Net8
Administrator’s Guide. For more information on how to configure a firewall, please
see your firewall’s documentation or contact your firewall vendor.
Packaging Applets
After you have coded your applet, you must package it and make it available to
users. To package an applet you need your applet classes files and the JDBC driver
classes file (this will be either classes111.zip if you are targeting the applet to a
browser running JDK 1.1.1, or classes102.zip if you are targeting the applet to a
browser running JDK 1.0.2).
Follow these steps:
1. Move the JDBC driver classes file classes111.zip (or classes102.zip) to
an empty directory.
2. Unzip the driver classes zip file.
If you are targeting a browser running the JDK 1.0.2, then DELETE the
packages listed in the left-hand column of the following table. Next, ensure that
the packages listed in the right-hand column are present. All of the packages
listed in the table are included in the JDBC distribution.
oracle.jdbc.driver oracle.jdbc.dnlddriver
oracle.jdbc.dbaccess oracle.jdbc.dnlddbaccess
oracle.jdbc.oracore oracle.jdbc.dnldoracore
oracle.jdbc.util oracle.jdbc.dnldutil
oracle.sql oracle.sdnldql
oracle.jdbc2 oracle.dnldjdbc2
java.io.Reader jdbc.io.Reader
java.io.Writer jdbc.io.Writer
3. Add your applet classes files to the directory, and any other files the applet
might require.
4. Zip the applet classes and driver classes together into a single zip (or .jar) file.
To target a browser running the JDK 1.1.1, the single zip file should contain:
■ the files from classes111.zip
■ your applet classes
■ If you are using DatabaseMetaData entry points in your applet, include the
oracle/jdbc/driver/OracleDatabaseMetaData.class file. Note
that this file is very large and might have a negative impact on
performance. If you do not use DatabaseMetadata entry points, omit this
file.
To target a browser running the JDK 1.0.2, the single zip file should contain:
■ the files from classes102.zip (minus the files you deleted in Step 2)
■ your applet classes
■ the jdbc interface files from the jdbc.sql package in the
classes/jdbc/sql directory of the JDBC distribution
You can find a description of the APPLET, CODE, ARCHIVE, CODEBASE, WIDTH, and
HEIGHT parameters in the next section.
If you use this form of the CODE tag, then the classes for the applet and the classes
for the JDBC Thin driver must be in the same directory as the HTML page.
Notice that in the CODE specification, you do not include the file name extension
".class".
CODEBASE
The CODEBASE parameter is optional and specifies the base URL of the applet; that
is, the name of the directory that contains the applet’s code. If it is not specified,
then the document’s URL is used. This means that the classes for the applet and the
JDBC Thin driver must be in the same directory as the HTML page. For example, if
the current directory is my_Dir:
The entry CODEBASE="." indicates that the applet resides in the current directory
(my_Dir). If the value of codebase was set to Applet_Samples, for example:
CODEBASE="Applet_Samples"
then this would indicate that the applet resides in the my_Dir/Applet_Samples
directory.
ARCHIVE
The ARCHIVE parameter is optional and specifies the name of the archive file (either
a .zip or .jar file) that contains the applet classes and resources the applet needs.
Oracle recommends the use of a .zip file, which saves many extra roundtrips to
the server.
The .zip (or .jar) file will be preloaded. If you have more than one archive in the
list, separate them with commas. In the following example, the class files are stored
in the archive file JdbcApplet.zip:
<APPLET CODE="JdbcApplet" ARCHIVE="JdbcApplet.zip" WIDTH=500 HEIGHT=200>
</APPLET>
netscape.security.PrivilegeManager.enablePrivilege
("UniversalConnect");
connection = DriverManager.getConnection
("jdbc:oracle:thin:scott/tiger@dlsun511:1721:orcl");
Please refer to your browser documentation for more information on how to work
with signed applets. You can also refer to "Using Signed Applets" on page 5-13.
import oracle.jdbc.driver.*;
class JDBCConnection {
public static Connection connect() throws SQLException {
Connection conn = null;
try {
// connect with the Server driver
OracleDriver ora = new OracleDriver();
conn = ora.defaultConnection();
}
} catch (SQLException e)
return conn;
}
}
Note that there is no conn.close statement. You cannot close a default connection
made by the Server driver. Calling close() on the connection is just a no-op.
Note that you could include a user name and password in the string, but because
you are connecting from the server, they would be ignored.
the client side where there is no default session: you must explicitly connect to the
database.
If you run Java application code in the server, then you can manage the transaction
(COMMITs and ROLLBACKs) explicitly.
The advantage of using this method is that you need to change only a short string in
your original program. The disadvantage is that you still must provide the user,
password, and database information even though the driver will discard it. In
addition, if you issue the getConnection() method again, the driver will create
another new (and unnecessary) connection object.
However, if you connect with defaultConnection(), the preferred method of
connecting to the database from the Server driver, you do not have to enter any
user, password, or database information. You can delete these statements from your
program.
For the connection statement, use:
Connection conn = new oracle.jdbc.driver.OracleDriver ().defaultConnection ();
/*
* This sample can be used to check the JDBC installation.
* Just run it and provide the connect information. It will select
* "Hello World" from the database.
*/
// You need to import the java.sql package to use JDBC
import java.sql.*;
// We import java.io to be able to read from the command line
import java.io.*;
class JdbcCheckup
{
public static void main (String args [])
throws SQLException, IOException
{
Connection conn = new oracle.jdbc.driver.OracleDriver
().defaultConnection ();
// Create a statement
Statement stmt = conn.createStatement ();
Date Literals
The JDBC drivers support date literals in SQL statements written in the format:
{d ’yyyy-mm-dd’}
where yyyy-mm-dd represents the year, month, and day; for example,
{d ’1998-10-22’}. The JDBC drivers will replace this escape clause with the
equivalent Oracle representation: "22 OCT 1998".
This code snippet contains an example of using a date literal in a SQL statement.
// Create a Statement
Statement stmt = conn.createStatement ();
// Select the ename column from the emp table where the hiredate is Jan-23-1982
ResultSet rset = stmt.executeQuery
("SELECT ename FROM emp WHERE hiredate = {d ’1982-01-23’}");
Time Literals
The JDBC drivers support time literals in SQL statements written in the format:
{t ’hh:mm:ss’}
where hh:mm:ss represents the hours, minutes, and seconds; for example,
{t ’05:10:45’}. The JDBC drivers will replace this escape clause with the
equivalent Oracle representation: "05:10:45". If the time is specified as
{t ’14:20:50’}, then the equivalent Oracle representation would be "14:20:50",
assuming the server is using a 24-hour clock.
This code snippet contains an example of using a time literal in a SQL statement.
ResultSet rset = stmt.executeQuery
("SELECT ename FROM emp WHERE hiredate = {t ’12:00:00’}");
Timestamp Literals
The JDBC drivers support timestamp literals in SQL statements written in the
format:
{ts ’yyyy-mm-dd hh:mm:ss.f...’}
Scalar Functions
The Oracle JDBC drivers do not support all scalar functions. To find out which
functions the drivers support, use the following methods which are supported by
the Oracle-specific oracle.jdbc.driver.OracleDatabaseMetaData and the
standard Java java.sql.DatabaseMetadata interfaces:
■ getNumericFunctions(): returns a comma-separated list of math functions
supported by the driver. For example, ABS(number), COS(float), SQRT(float).
■ getStringFunctions(): returns a comma-separated list of string functions
supported by the driver. For example, ASCII(string), LOCATE(string1, string2,
start).
■ getSystemFunctions(): returns a comma-separated list of system functions
supported by the driver. For example, DATABASE(), IFNULL(expression, value),
USER().
■ getTimeDateFunctions(): returns a comma-separated list of time and date
functions supported by the driver. For example, CURDATE(), DAYOFYEAR(date),
HOUR(time).
Oracle’s JDBC drivers do not support the function keyword, ’fn’. If you try to use
this keyword, for example:
{fn concat ("Oracle", "8i") }
you will get the error "Non supported SQL92 token at position xx: fn"
when you run your Java application. The work-around is to use Oracle SQL syntax.
For example, instead of using the fn keyword in embedded SQL92 syntax:
Statement stmt = conn.createStatement ();
stmt.executeUpdate("UPDATE emp SET ename = {fn CONCAT(’My’, ’Name’)}");
// Select the empno column from the emp table where the ename starts with ’_’
ResultSet rset = stmt.executeQuery("SELECT empno FROM emp WHERE ename LIKE ’&_%’
{ESCAPE ’&’}");
Note: If you want to use the back slash character (\) as an escape
character, you must enter it twice (that is, \\). For example:
ResultSet rset = stmt.executeQuery("SELECT empno FROM emp WHERE
ename LIKE ’\\_%’ {escape ’\\’}");
Outer Joins
Oracle’s JDBC drivers do not support outer join syntax: {oj outer-join}. The
work-around is to use Oracle outer join syntax:
Instead of:
Statement stmt = conn.createStatement ();
ResultSet rset = stmt.executeQuery
("SELECT ename, dname
FROM {OJ dept LEFT OUTER JOIN emp ON dept.deptno = emp.deptno}
ORDER BY ename");
The following code is the output which prints the comparable SQL syntax.
{call foo(?, ?)} => BEGIN foo(:1, :2); END;
{? = call bar (?, ?)} => BEGIN :1 := bar (:2, :3); END;
{d ’1998-10-22’} => TO_DATE (’1998-10-22’, ’YYYY-MM-DD’)
{t ’16:22:34’} => TO_DATE (’16:22:34’, ’HH24:MI:SS’)
{ts ’1998-10-22 16:22:34’} => TO_DATE (’1998-10-22 16:22:34’, ’YYYY-MM-DD
HH24:MI:SS’)
int m_myId;
System.exit(0);
}
else if (args.length == 1)
NUM_OF_THREADS = Integer.parseInt (args[0]);
// spawn threads
for (int i = 0; i < NUM_OF_THREADS; i++)
{
threadList[i] = new JdbcMTSample();
threadList[i].start();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
public JdbcMTSample()
{
super();
// Assign an ID to the thread
m_myId = getNextId();
}
try
{
// Get the connection
conn = DriverManager.getConnection("jdbc:oracle:oci8:@",
"scott","tiger");
// Create a Statement
stmt = conn.createStatement ();
Performance Optimization
You can significantly enhance the performance of your JDBC programs by using
any of these features:
■ Disabling Auto-Commit Mode
■ Prefetching Rows
■ Batching Updates
Example: Disabling AutoCommit The following example illustrates loading the driver
and connecting to the database. Since new connections are in auto-commit mode by
default, this example shows how to disable auto-commit. In the example, conn
represents the Connection object and stmt represents the Statement object.
// Load the Oracle JDBC driver
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
// Create a Statement
Statement stmt = conn.createStatement ();
...
Prefetching Rows
Oracle JDBC drivers allow you to set the number of rows to prefetch into the client
while the result set is being populated during a query. The default number of rows
to prefetch is 10. Prefetching row data into the client reduces the number of round
trips to the server. In contrast, standard JDBC fetches the result set one row at a
time, where each row requires a round trip to the database.
You can set the row prefetching value for an individual statement or for all
statements in your connection. For a description of row prefetching and how to
enable it, see "Row Prefetching" on page 4-98.
Batching Updates
The Oracle JDBC drivers allow you to accumulate inserts and updates of prepared
statements at the client and send them to the server in batches once it reaches a
specified batch value. This feature reduces round trips to the server. The default
batch value is one.
You can set the batch value for any individual Oracle prepared statement or for all
Oracle prepared statements in your Oracle connection. For a description of update
batching and how to enable it, see "Database Update Batching" on page 4-100.
Common Problems
This section describes some common problems that you might encounter while
using the Oracle JDBC drivers. These problems include:
■ Space Padding for CHAR Columns Defined as OUT or IN/OUT Variables
■ Memory Leaks and Running Out of Cursors
■ Boolean Parameters in PL/SQL Stored Procedures
■ Opening More Than 16 OCI Connections for a Process
Trapping Exceptions
Most errors that occur in JDBC programs are handled as exceptions. Java provides
the try...catch statement to catch the exception and the printStackTrace()
method to print the stack trace.
The following code fragment illustrates how you can catch SQL exceptions and
print the stack trace.
try { <some code> }
catch(SQLException e){ e.printStackTrace (); }
To illustrate how the JDBC drivers handle errors, the following incorrect code was
intentionally added to the Employee.java sample:
// Iterate through the result and print the employee names
// of the code
try {
while (rset.next ())
System.out.println (rset.getString (5)); } // incorrect column index
catch(SQLException e){ e.printStackTrace (); }
For more information on how the JDBC drivers handle errors, and the
SQLException() and the printStackTrace() methods, see "Error Messages
and JDBC" on page 3-25.
Note: The trace facility uses a large amount of disk space and
might have significant impact upon system performance. Therefore,
enable tracing only when necessary.
Client-Side Tracing
Set the following parameters in the SQLNET.ORA file on the client system.
TRACE_LEVEL_CLIENT
TRACE_DIRECTORY_CLIENT
TRACE_FILE_CLIENT
TRACE_UNIQUE_CLIENT
Purpose: Gives each client-side trace a unique name to prevent each trace file from
being overwritten with the next occurrence of a client trace. The PID is
attached to the end of the file name.
Default Value: OFF
Example: TRACE_UNIQUE_CLIENT = ON
Server-Side Tracing
Set the following parameters in the SQLNET.ORA file on the server system. Each
connection will generate a separate file with a unique file name.
TRACE_LEVEL_SERVER
TRACE_DIRECTORY_SERVER
TRACE_FILE_SERVER
This chapter presents sample applications that highlight advanced JDBC features
and Oracle extensions, including the following topics:
■ Sample Applications for Basic JDBC Features
■ Sample Applications for JDBC 2.0-Compliant Oracle Extensions
■ Sample Applications for Other Oracle Extensions
■ Creating Customized Java Classes for Oracle Objects
■ Creating Signed Applets
■ JDBC versus SQLJ Sample Code
Streaming Data
The JDBC drivers support the manipulation of data streams in both directions
between client and server. The code sample in this section demonstrates this by
using the JDBC OCI driver for connecting to a database, and inserting and fetching
LONG data using Java streams.
import java.sql.*; // line 1
import java.io.*;
class StreamExample
{
public static void main (String args [])
throws SQLException, IOException
{
// Load the driver
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
// Create a Statement
Statement stmt = conn.createStatement ();
// Loop, reading from the gif stream and writing to the file
int c;
while ((c = gif_data.read ()) != -1)
os.write (c);
Lines 1-18: Import the necessary classes. Load the JDBC OCI driver with the
DriverManager.registerDriver() method. Connect to the database with the
getConnection(), as user scott with password tiger. Use the database URL
jdbc:oracle:oci8:@. You can optionally enter a database name after the @
symbol. Disable AUTOCOMMIT to enhance performance. If you do not, the driver
will issue execute and commit commands after every SQL statement.
Line 34: Create a table STREAMEXAMPLE with a NAME column of type VARCHAR and
a DATA column of type LONG.
Lines 37-44: Insert the contents of the StreamExample.java into the table. To do
this, create an input stream object for the Java file. Then, prepare a statement to
insert character data into the NAME column and the stream data into the DATA
column. Insert the NAME data with the setString(); insert the stream data with
setAsciiStream().
Line 46: Query the table to get the contents of the DATA column into a result set.
Line 51-66: Get the data from the first row of the result set into the InputStream
object gif_data. Create a FileOutputStream to write to the specified file object.
Then, read the contents of the gif stream and write it to the file example.out.
LOB Sample
This sample demonstrates basic support for LOBs in the OCI 8 driver. It illustrates
how to create a table containing LOB columns, and includes utility programs to
read from a LOB, write to a LOB, and dump the LOB contents. For more
information on LOBs, see "Working with LOBs" on page 4-45.
Except for some changes to the comments, the following sample is similar to the
LobExample.java program in the Demo/samples/oci8/object-samples
directory.
import java.sql.*; // line 1
import java.io.*;
import java.util.*;
// Create a Statement
Statement stmt = conn.createStatement ();
try
{
stmt.execute ("DROP TABLE basic_lob_table");
}
catch (SQLException e)
{
// An exception could be raised here if the table did
// not exist already but we gleefully ignore it
} // line 38
{
// Get the lobs
BLOB blob = ((OracleResultSet)rset).getBLOB (2);
CLOB clob = ((OracleResultSet)rset).getCLOB (3);
// Fetch data
while ((length = instream.read(buffer)) != -1)
{
System.out.print("Read " + length + " bytes: ");
int i = 0;
i += chunk;
if (length - i < chunk)
chunk = (int) length - i;
}
outstream.close();
} // line 154
int i = 0;
i += chunk;
if (length - i < chunk)
chunk = (int) length - i;
}
outstream.close();
}
} // line 175
Lines 1-26: Import the necessary java.* and oracle.* classes. Register the driver
with the DriverManager.registerDriver() method and connect to the
database with DriverManager.getConnection(). Use the database URL
jdbc:oracle:oci8:@ and connect as user scott with password tiger. You can
optionally enter a database name following the @ symbol.
Lines 27-38: Create a statement object. Drop any pre-existing table named
basic_lob_table. Then, create a new basic_lob_table directory to store the
LOBs in-line.
Lines 40-49: Use SQL statements to create a table with three columns: a column to
store the row number as a VARCHAR2, a BLOB column, and a CLOB column. Then
insert data into two rows of the table.
Lines 50-68: SELECT the contents of the table into a result set.
Retrieve the LOBs. The getBLOB() and getCLOB() methods return locators to the
LOB data; to retrieve the LOB contents, you must write additional code (which is
defined later in this program). To use the getBLOB() and getCLOB() methods,
cast the result set to an OracleResultSet object. Then call the "dump" functions to
display the contents of the LOBs, and the "fill" functions to change the contents of
the LOBs. The dump and fill functions are defined later in this program.
Lines 69-82: Display the LOBs again, after their contents have been changed.
SELECT the contents of the table into a result set, and then apply the dump
functions. The dump functions are defined later in this program.
Lines 84-108: Define the utility function dumpClob to display the contents of a CLOB.
Read the CLOB contents as a character stream. Use the getCharacterStream()
method to get a READER stream object. Set up the temporary character array to read
the character data in 10-character chunks.
Set up a loop to read and display the contents of the CLOB. The length of the CLOB is
displayed as well. Close the input stream when you are done.
Lines 110-135: Define the utility function dumpBlob to display the contents of a
BLOB. Read the BLOB contents as a binary stream. Use the getBinaryStream()
method to get an InputStream stream object. Set up the temporary byte array to
read the binary data in 10-byte chunks.
Set up a loop to read and display the contents of the BLOB. The length of the BLOB is
displayed as well. Close the input stream when you are done.
Lines 136-154: Define the utility function fillClob to write data to a CLOB. The
fillClob function needs the CLOB locator and the length of the CLOB. To write to
Lines 156-175: Define the utility function fillBlob to write data to a BLOB. The
fillBlob function needs the BLOB locator and the length of the BLOB. To write to
the BLOB, use the getBinaryOutputStream() method to get an OutputStream
object.
Define the byte array of data that you want to write to the BLOB. The while loop
causes a variation of the data to be written to the BLOB. Close the OutputStream
object when you are done.
BFILE Sample
This sample demonstrates basic BFILE support in the OCI 8 driver. It illustrates
filling a table with BFILEs and includes a utility for dumping the contents of a
BFILE. For more information on BFILEs, see "Working with LOBs" on page 4-45.
Except for some changes to the comments, the following sample is similar to the
FileExample.java program in the Demo/samples/oci8/object-samples
directory.
import java.sql.*; // line 1
import java.io.*;
import java.util.*;
//
// The example creates a DIRECTORY and you have to be connected as
// "system" to be able to run the test.
// If you can’t connect as "system" have your system manager
// create the directory for you, grant you the rights to it, and
// remove the portion of this program that drops and creates the directory.
Connection conn =
DriverManager.getConnection ("jdbc:oracle:oci8:@", "system", "manager");
try // line 36
{
stmt.execute ("DROP DIRECTORY TEST_DIR");
}
catch (SQLException e)
{
// An error is raised if the directory does not exist. Just ignore it.
} // line 43
stmt.execute ("CREATE DIRECTORY TEST_DIR AS ’/temp/filetest’");
try // line 46
{
stmt.execute ("drop table test_dir_table");
}
catch (SQLException e)
{
// An error is raised if the table does not exist. Just ignore it.
}
// line 54
// Create and populate a table with files
// The files file1 and file2 must exist in the directory TEST_DIR created
// above as symbolic name for /private/local/filetest.
stmt.execute ("CREATE TABLE test_dir_table (x varchar2 (30), b bfile)");
stmt.execute ("INSERT INTO test_dir_table VALUES (’one’, bfilename
(’TEST_DIR’, ’file1’))");
stmt.execute ("INSERT INTO test_dir_table VALUES (’two’, bfilename
(’TEST_DIR’, ’file2’))");
bfile.openFile();
// Fetch data
while ((length = instream.read(buffer)) != -1)
{
System.out.print("Read " + length + " bytes: ");
Lines 1-32: Import the necessary java.* and oracle.* classes. Register the driver
with the DriverManager.registerDriver() method and connect to the
database with the getConnection() method. Use the database URL
jdbc:oracle:oci8:@ and connect as user system with password manager. You
can optionally enter a database name following the @ symbol.
Use setAutoCommit(false) to disable the AUTOCOMMIT feature and enhance
performance. If you do not, the driver will issue execute and commit commands
after every SQL statement.
Lines 33-44: Create a statement object. Drop any pre-existing directory named
TEST_DIR. Then, create a new TEST_DIR directory to store the BFILE. You or your
System Administrator can use whatever file name you wish.
Lines 55-63: Create and populate a table with files. Use SQL statements to create a
table, test_dir_table, with two columns: one column to indicate the row
number as a VARCHAR2 (for example, "one" or "two"), and one column to hold the
BFILE locator.
Use SQL statements to insert some data into the table. For the first row, insert a row
number in the first column, and use the BFILENAME keyword to insert a BFILE,
file1, located in TEST_DIR, in the second column. Do the same thing for the
second row.
Lines 64-75: SELECT the contents of the table into a result set. Set up a loop to
retrieve the contents of the table. Use getString() to retrieve the row number
data, and use getBFILE() to retrieve the BFILE locator. Since BFILE is an
Oracle-specific datatype, and getBFILE() is an Oracle extension, cast the result set
object to an OracleResultSet object.
Use the dumpBfile() method (defined later in the program) to display the BFILE
contents and various statistics about the BFILE.
Line 77: Define the dumpBfile() method to display the BFILE contents and
various statistics about the BFILE. The dumpBfile() method takes the BFILE
locator as input.
Lines 84-108: Read and display the BFILE contents. First open the BFILE. You can
read the BFILE contents as a binary stream. Use the getBinaryStream() method
to get an input stream object. Determine the size of the "chunk" in which the stream
will read the BFILE data, and set up the temporary byte array to store the data.
Set up a loop to read and display the contents of the BFILE. The length of the
BFILE is displayed as well.
Lines 110-115: When you are finished, close the input stream and the BFILE.
class RefCursorExample
{
public static void main(String args[]) throws SQLException
{
//Load the driver.
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Lines 1-16: Import the necessary java.* and oracle.* classes. Register the driver
with the DriverManager.registerDriver() method and connect to the
database with the getConnection() method. Use the database URL
jdbc:oracle:oci8:@ and connect as user scott with password tiger. You can
optionally enter a database name following the @ symbol.
Lines 30-33: Iterate through the result set and print the employee name part of the
employee object.
Lines 40-45: Define the package header for the java_refcursor package. The
package header defines the return types and function signatures.
Lines 46-53: Define the package body for the java_refcursor package. The
package body defines the implementation which selects rows based on the value for
job.
Array Sample
Following is a complete sample program that uses JDBC to create a table with a
VARRAY. It inserts a new array object into the table, then prints the contents of the
table. For more information on arrays, see "Working with Arrays" on page 4-87.
Except for some changes to the comments, the following sample is similar to the
ArrayExample.java program in the Demo/samples/oci8/object-samples
directory.
import java.sql.*; // line 1
import oracle.sql.*;
import oracle.jdbc.oracore.Util;
import oracle.jdbc.driver.*;
import java.math.BigDecimal;
Connection conn =
DriverManager.getConnection
("jdbc:oracle:oci8:@(description=(address=(host=hostname)(protocol=tcp)(port=por
t_number))(connect_data=(sid=sid_name)))", "scott", "tiger");
// Create a Statement
Statement stmt = conn.createStatement (); // line 35
try
{
stmt.execute ("DROP TABLE varray_table");
stmt.execute ("DROP TYPE num_varray");
}
catch (SQLException e)
{
// the above drop statements will throw exceptions
// if the types and tables did not exist before
} // line 47
ps.execute ();
} // line 97
Lines 1-32: Import the necessary java.* and oracle.* classes. Register the driver
with the DriverManager.registerDriver() method and connect to the
database with the getConnection() method. This example of
getConnection() uses Net8 name-value pairs to specify the host as hostname,
protocol as tcp, port as 1521, sid as orcl, user as scott and password as
tiger.
Use setAutoCommit(false) to disable the AUTOCOMMIT feature and enhance
performance. If you do not, the driver will issue execute and commit commands
after every SQL statement.
Lines 35-47: Create a Statement object and delete any previously defined tables or
types named varray_table or num_varray.
Lines 49-54: Create the type num_varray as a varray containing NUMBER data.
Create a 1-column table, varray_table, to contain the num_varray type data.
Insert into the table two rows of data. The values 100 and 200 are both of type
num_varray. Use the showResultSet() method (defined later in the program) to
display information about the arrays contained in the table.
Lines 59-61: First, define an array of integer elements to insert into the
varray_table. Next, create an array descriptor object that will be used to create
new ARRAY objects. To create an array descriptor object, pass the SQL type name of
the array type (NUM_ARRAY) and the connection object to the
createDescriptor() method. Then create the new array object by passing to it
the array descriptor, the connection object, and the array of integer elements.
Lines 63-70: Prepare a statement to insert the new array object into varray_table.
Cast the prepared statement object to an OraclePreparedStatement object to
take advantage of the setARRAY() method.
To retrieve the array contents of the table, write and execute a SQL SELECT
statement. Again, use the showResultSet method (defined later in the program)
to display information about the arrays contained in the table.
Lines 72-85: Define the showResultSet() method. This method loops through a
result set and returns information about the arrays it contains. This method uses the
result set getARRAY() method to return an array into an oracle.sql.ARRAY
object. To do this, cast the result set to an OracleResultSet object. Once you have
the ARRAY object, you can apply Oracle extensions getSQLTypeName(),
getBaseType(), as well as length(), to return and display the SQL type name
of the array, the SQL type code of the array elements, and the array length.
Lines 87-97: You can access the varray elements by using the ARRAY object’s
getArray() method. Since the varray contains SQL numbers, cast the result of
getArray() to a java.math.BigDecimal array. Then, iterate through the value
array and pull out individual elements.
SQLData Sample
This section contains a code sample that illustrates how you can create a custom
Java type to correspond to a given SQL type. It then demonstrates how you can use
the custom Java class in the context of a sample program. The sample also contains
the code to map the SQL type to the custom Java type.
public EmployeeObj()
{
}
// line 14
public EmployeeObj (String sql_type, String empName, int empNo)
{
this.sql_type = sql_type;
this.empName = empName;
this.empNo = empNo;
} // line 20
// define a get method to return the SQL type of the object line 24
public String getSQLTypeName() throws SQLException
{
return sql_type;
} // line 28
empName = stream.readString();
empNo = stream.readInt();
}
// define the required writeSQL() method line 39
public void writeSQL(SQLOutput stream)
throws SQLException
{
stream.writeString(empName);
stream.writeInt(empNo);
}
}
Lines 1-14: Import the needed java.* and oracle.* packages. Define the custom
Java class EmployeeObj to implement the SQLData interface. EmployeeObj is the
class to which you will later map your EMPLOYEE SQL object type. The
EmployeeObj object has three attributes: a SQL type name, an employee name,
and an employee number. The SQL type name is a Java string that represents the
fully qualified SQL type name (schema.sql_type_name) of the Oracle object that the
custom Java class represents.
Lines 24-28: Define a getSqlType() method to return the SQL type of the custom
Java object.
catch (SQLException e)
{
// An error is raised if the table/type does not exist. Just ignore it.
}
pstmt.setObject(1, e, OracleTypes.STRUCT);
pstmt.executeQuery();
System.out.println("insert done");
pstmt.close(); // line 52
if (conn != null)
{
conn.close(); // line 72
}
}
Lines 1-16: Import needed java.* and oracle.* packages. Register the driver
with the DriverManager.registerDriver() method and connect to the
database with the getConnection() method. Use the database URL
jdbc:oracle:oci8:@ and connect as user scott with password tiger. You can
optionally enter a database name following the @ symbol.
Lines 18-21: Use the getTypeMap() method to get the type map associated with
this connection. Use the map object’s put() method to add the mapping of the SQL
EMPLOYEE object to the EmployeeObj custom Java type.
Lines 23-33: Create a statement object and drop any pre-existing tables and types
named EMPLOYEE_TABLE and EMPLOYEE.
Lines 42, 43: Create a new EmployeeObj object (which is a SQLData object).
Identify the schema name (SCOTT), SQL type name (EMPLOYEE), an employee name
(George Jones) and an employee number (456). Note that the schema name is the
same as the user name in the getConnection() call. If you change the user name,
you must also change the schema name.
Lines 45-52: Prepare a statement to insert the new EMPLOYEE object into the
employee table. The setObject() method indicates that the object will be inserted
into the first index position and that the underlying type of the EMPLOYEE object is
oracle.sql.STRUCT.
Lines 54-57: Select the contents of the EMPLOYEE_TABLE. Cast the results to an
OracleResultSet so that you can retrieve the custom Java object data from it.
Lines 59-62: Iterate through the result set, getting the contents of the EMPLOYEE
objects and printing the employee names and employee numbers.
Lines 66-72: Close the result set, statement, and connection objects.
CustomDatum Sample
This section describes a Java class, written by a user, that implements the
CustomDatum and CustomDatumFactory interfaces. The custom Java class of
type CustomDatum has a static getFactory() method that returns a
CustomDatumFactory object. The JDBC driver uses the CustomDatumFactory
object’s create() method to return a CustomDatum instance. Note that instead of
writing the custom Java class yourself, you can use the JPublisher utility to generate
class definitions that implement the CustomDatum and CustomDatumFactory
interfaces.
The following example illustrates a Java class definition that can be written by a
user, given the SQL definition of an EMPLOYEE object.
return _employeeFactory;
} // line 18
/* constructor */ // line 20
public Employee(String empName, BigDecimal empNo)
{
this.empName = empName;
this.empNo = empNo;
} // line 25
System.out.println(d);
/* fields */
public String empName;
public BigDecimal empNo;
}
Line 10: As required, the Employee class implements the CustomDatum and
CustomDatumFactory interfaces.
Lines 20-25: JPublisher defines the Employee Java class to correspond to the SQL
EMPLOYEE object. JPublisher creates the Employee class with two attributes: an
employee name of type java.lang.String and an employee number of type
java.math.BigDecimal.
Lines 27-36: The toDatum() method of the CustomDatum interface transforms the
EMPLOYEE SQL data into oracle.sql.* representation. To do this, toDatum()
uses:
■ a STRUCT descriptor that takes the schema name, the SQL object or "type"
name, and the connection object as arguments
■ an object array that stores the values of the object’s employee name and
employee number attributes
The toDatum() returns a STRUCT containing the STRUCT descriptor, the
connection object and the object attributes into an oracle.sql.Datum.
// Connect
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver ());
OracleConnection conn = (OracleConnection)
DriverManager.getConnection("jdbc:oracle:oci8:@",
"scott", "tiger");
pstmt.setObject(1, e, OracleTypes.STRUCT);
pstmt.executeQuery();
System.out.println("insert done");
pstmt.close(); // line 47
Statement s = conn.createStatement();
OracleResultSet rs = (OracleResultSet)
s.executeQuery("SELECT * FROM employee_table");
while(rs.next()) // line 54
{
Employee ee = (Employee) rs.getCustomDatum(1, Employee.getFactory());
System.out.println("EmpName: " + ee.empName + " EmpNo: " + ee.empNo);
} // line 58
rs.close();
s.close();
if (conn != null)
{
conn.close();
}
}
}
Lines 1-16: Import needed java.* and oracle.* packages. Register the driver
with the DriverManager.registerDriver() method and connect to the
database with the getConnection() method. Use the database URL
jdbc:oracle:oci8:@ and connect as user system with password manager. You
can optionally enter a database name following the @ symbol.
Lines 18-28: Create a statement object and drop any pre-existing tables and types
named EMPLOYEE_TABLE and EMPLOYEE.
Lines 37, 38: Create a new Employee object (which is a CustomDatum object) and
define an employee name and employee number for it.
Lines 40-47: Prepare a statement to insert the new Employee object into the
database. The setObject() method indicates that the object will be inserted into
the first index position and that the underlying type of the Employee object is
oracle.sql.STRUCT.
Lines 49-54: Select the contents of the employee_table. Cast the results to an
OracleResultSet so that the getCustomDatum() method can be used on it.
Lines 54-58: Iterate through the result set, getting the contents of the Employee
objects and printing the employee names and employee numbers.
Lines 58-62: Close the result set, statement, and connection objects.
Follow the instructions for obtaining a certificate and downloading the classes.
The example in this section requires the Capabilities classes
Principle.class, Privilege.class, PrivilegeManager.class, and
PrivilegeTable.class.
In the applet code, replace the following strings:
■ Replace <local database connect string> with the connect string for
the local database. For example:
"jdbc:oracle:thin:@myServer.us.oracle.com:1521:orcl", "scott","tiger"
■ Replace <remote database connect string> with the connect string for
the remote database. For example:
"jdbc:oracle:thin:@yourServer.us.oracle.com:1521:orcl", "scott","tiger"
This applet uses only the Java AWT components and JDBC.
// Title: JDBC Test Applet // line 1
// Description:Sample JDK 1.1 Applet using the
// ORACLE JDBC Thin Driver
package JDBCApplet;
public MainApplet() {
}
//Main method
static public void main(String[] args) {
MainApplet applet = new MainApplet();
applet.isStandalone = true;
Frame frame = new Frame();
frame.setTitle("Applet Frame");
frame.add(applet, BorderLayout.CENTER);
applet.init();
applet.start();
frame.pack();
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((d.width - frame.getSize().width) / 2, (d.height -
frame.getSize().height) / 2);
frame.setVisible(true);
}
void button1_actionPerformed(ActionEvent e) {
//
// Handler for "Local" Button.
//
// Here is where we connect to local database line 121
try {
DriverManager.registerDriver ( new oracle.jdbc.driver.OracleDriver ());
b.append ("DriverManager.registerDriver\r\n");
} catch (SQLException oe) {
statusBar1.setText("registerDriver: Caught SQLException");
} catch (ClassNotFoundException oe) {
statusBar1.setText("registerDriver: Caught ClassNotFoundException");
}
int numRows = 0;
try {
statusBar1.setText("Executing Query on Local Database ...");
Connection conn = DriverManager.getConnection (
"jdbc:oracle:thin:<local database connect string>");
void button2_actionPerformed(ActionEvent e) {
//
// Handler for the "Remote" Button line 170
//
StringBuffer b = new StringBuffer ();
try {
DriverManager.registerDriver ( new oracle.jdbc.driver.OracleDriver ());
b.append ("DriverManager.registerDriver\r\n");
} catch (SQLException oe) {
statusBar1.setText("registerDriver: Caught SQLException");
} catch (ClassNotFoundException oe) {
statusBar1.setText("registerDriver: Caught ClassNotFoundException");
}
}
}
// line 260
class MainApplet_button1_actionAdapter implements java.awt.event.ActionListener
{
MainApplet adaptee;
MainApplet_button1_actionAdapter(MainApplet adaptee) {
this.adaptee = adaptee;
}
MainApplet_button2_actionAdapter(MainApplet adaptee) {
this.adaptee = adaptee;
}
Lines 13-26: Set up the graphics for the GUI which will include two buttons and a
text area to display the output.
Lines 37-48: Request privileges to connect to the host other than the one from which
the applet was downloaded.
Lines 49-77: Initialize the components of the applet. These components include the
format and layout of the GUI and the GUI buttons and text area.
Lines 121-165: Connect to the local database. To do this, register the driver with the
DriverManager.registerDriver() method and connect to the database with
DriverManager.getConnection(). Connect with the server URL, port number,
SID, user name, and password.
Lines 183-256: Test that the applet has privileges on the remote database. If it does,
then connect to the database and execute SQL statements.
Lines 260-283: Code to set up events and callbacks for the buttons.
Note: The JDBC and SQLJ versions of the sample code are only
code snippets. They cannot be run independently.
(
name VARCHAR(30),
ssn NUMBER,
addr address
)
/
/*** Create a relational table with two columns that are REFs
to person objects, as well as a column which is an Address object.***/
/
/*** insert code for UPDATE_ADDRESS stored procedure here
/
/** Set the manager and person REFs for the employee **/
UPDATE employees
SET manager =
(SELECT REF(p) FROM persons p WHERE p.name = ’Wolfgang Amadeus Mozart’)
/
UPDATE employees
SET person_data =
(SELECT REF(p) FROM persons p WHERE p.name = ’Ludwig van Beethoven’)
/
COMMIT
/
QUIT
/**
This is what we have to do in JDBC
**/
public class SimpleDemoJDBC // line 7
{
{
OracleCallableStatement cstmt = (OracleCallableStatement)
conn.prepareCall("{ ? = call UPDATE_ADDRESS(?) }"); //line 34
cstmt.registerOutParameter(1, Address._SQL_TYPECODE, Address._SQL_NAME);
// line 36
if (addr == null) {
cstmt.setNull(2, Address._SQL_TYPECODE, Address._SQL_NAME);
} else {
cstmt.setCustomDatum(2, addr);
}
cstmt.executeUpdate(); // line 43
addr = (Address)cstmt.getCustomDatum(1, Address.getFactory());
cstmt.close(); // line 45
return addr;
}
}
Line 12: In the getEmployeeAddress() method definition, you must pass the
connection object to the method definition explicitly.
Lines 16-20: Prepare a statement that selects an employee’s address from the
employees table on the basis of the employee number. The employee number is
represented by a marker variable, which is set with the setInt() method. Note
that because the prepared statement does not recognize the "INTO" syntax used in
"SQL Program to Create Tables and Objects" on page 7-39, you must provide your
own code to populate the address (addr) variable. Since the prepared statement is
returning a custom object, cast the output to an Oracle result set.
Lines 21-23: Because the Oracle result set contains a custom object of type Address,
use the getCustomDatum() method to retrieve it (the Address object could be
created by JPublisher). The getCustomDatum() method requires you to use the
factory method Address.getFactory() to materialize an instance of an
Lines 25-27: Close the result set and prepared statement objects, then return the
addr variable.
Line 29: In the updateAddress() definition, you must pass the connection object
and the Address object explicitly.
The updateAddress() method passes an address to the database for update and
fetches it back. The actual updating of the address is performed by the
UPDATE_ADDRESS stored procedure (the code for this procedure is not illustrated
in this example).
Line 33-43: Prepare an Oracle callable statement that takes an address object
(Address) and passes it to the UPDATE_ADDRESS stored procedure. To register an
object as an output parameter, you must know the object’s SQL type code and SQL
type name.
Before passing the address object (addr) as an input parameter, the program must
determine whether addr has a value or is null. Depending on the value of addr, the
program calls different set methods. If addr is null, the program calls setNull(),
if it has a value, the program calls setCustomDatum().
Line 44: Fetch the return result addr. Since the Oracle callable statement returns a
custom object of type Address, use the getCustomDatum() method to retrieve it
(the Address object could be created by JPublisher). The getCustomDatum()
method requires you to use the factory method Address.getFactory to
materialize an instance of an Address object. Because getCustomDatum() returns
a Datum, cast the output to an Address object.
Lines 45, 46: Close the Oracle callable statement, then return the addr variable.
■ Long SQL strings must be concatenated with the SQL concatenation character
("+").
■ You must explicitly manage resources (for example, close result set and
statement objects).
■ You must cast datatypes as needed.
■ You must know the _SQL_TYPECODE and _SQL_NAME of the factory objects
that you are registering as output parameters.
■ Null data must be explicitly handled.
■ Host variables must be represented by parameter markers in callable and
prepared statements.
/**
This is what we have to do in SQLJ
**/
public class SimpleDemoSQLJ // line 6
{
//TO DO: make a main that calls this?
}
// line 18
public Address updateAddress(Address addr)
throws SQLException
{
#sql addr = { VALUES(UPDATE_ADDRESS(:addr)) }; // line 23
return addr;
}
}
Line 19: The updateAddress() method also uses the default connection context
instance.
Lines 19-23: The address is passed to the updateAddress() method, which passes
it to the database. The database updates it and passes it back. The actual updating
of the address is performed by the UPDATE_ADDRESS stored function (the code for
this function is not shown here). Use standard SQLJ function-call syntax to receive
the address object (addr) output by UPDATE_ADDRESS.
This chapter contains detailed JDBC reference information, including the following
topics:
■ Valid SQL-JDBC Datatype Mappings
■ Supported SQL and PL/SQL Datatypes
■ NLS Character Set Support
■ Related Information
Table 8–1 lists all of the possible Java classes to which a given SQL datatype can be
validly mapped. The Oracle JDBC drivers will support these "non-default"
mappings. For example, to materialize SQL CHAR data as an oracle.sql.CHAR,
use getCHAR(). To materialize it as a java.math.BigDecimal, use
getBigDecimal().
Notes:
■ The type UROWID is not supported.
■ oracle.sql.Datum is an abstract class. The value passed to a
parameter of type oracle.sql.Datum must be of the Java
type corresponding to the SQL type. Likewise, the value
returned by a method with return type oracle.sql.Datum
must be of the Java type corresponding to the SQL type.
■ The mappings to oracle.sql classes are optimal if no
conversion from SQL format to Java format is necessary.
Table 8–3 describes Oracle JDBC driver and SQLJ support for the ANSI-supported
SQL datatypes.
Table 8–4 describes Oracle JDBC driver and SQLJ support for PL/SQL datatypes.
Note that PL/SQL datatypes include these categories:
■ scalar types
■ scalar character types (includes boolean and date datatypes)
■ composite types
■ reference types
■ LOB types
Notes:
■ The types natural, naturaln, positive, positiven, and signtype
are subtypes of binary integer.
■ The types dec, decimal, double precision, float, int, integer,
numeric, real, and smallint, are subtypes of number.
Related Information
This section lists web sites that contain useful information for JDBC programmers.
Many of the sites are referenced in other sections of this manual. In this list you can
find references to the Oracle JDBC drivers and SQLJ, Java technology, the Java
Developer’s Kit APIs (for versions 1.2 and 2.0), and resources to help you write
applets.
Java Technology
Java Technology Home Page (Sun Microsystems, Inc.):
http://www.javasoft.com/
Signed Applets
Introduction to Capabilities Classes (Netscape Communications Corp.):
http://developer.netscape.com/docs/manuals/signedobj/capabilities/contents.htm
This appendix lists the error messages that the Oracle JDBC drivers can return.
"Cause" and "Action" information for each message will be provided in a later
release.
byte array not long enough
closed connection
closed LOB
closed resultset
closed statement
exception in OracleNumber
exhausted resultset
Internal error: attempt to access bind values beyond the batch value
invalid cursor
missing defines
missing descriptor
no data read
numeric overflow
protocol violation
undefined type
unsupported feature
Index-1
passing to callable statements, 4-56 class, 4-17
passing to prepared statements, 4-56 creating and populating, 4-52
manipulating data, 4-60 creating columns, 4-52
reading data, 4-57 locators, 4-46
working with, 4-45 getting from result set, 4-46
BFILE locator, selecting, 4-18 passing to callable statements, 4-48
BLOB, 4-48 passing to prepared statement, 4-48
class, 4-17 locators, selecting, 4-18
creating and populating, 4-52 manipulating data, 4-54
creating columns, 4-52 populating columns, 4-53
getting locators, 4-46 reading data, 4-48, 4-50
locators working with, 4-45
getting from result set, 4-46 writing data, 4-51
selecting, 4-18 close() method, 4-25, 4-26, 4-27, 6-7
manipulating data, 4-54 for database connection, 5-23
populating columns, 4-53 closeFile() method, 4-19
reading data, 4-48, 4-50 CMAN.ORA file, creating, 5-11
working with, 4-45 CODE, parameter for APPLET tag, 5-19
writing data, 4-51 CODEBASE, parameter for APPLET tag, 5-19
Boolean parameters, restrictions, 6-7 collections, 4-87
browser security, 5-20 collections (nested tables and arrays), 4-15
column types
redefining, 4-97, 4-105
C
restrictions on, 4-105
callable statement COMMIT operation, 5-24
getting a BFILE locator, 4-56 connect string
getting LOB locators, 4-47 for KPRB driver, 5-23
passing BFILE locator, 4-56 for the Oracle8 Connection Manager, 5-12
passing LOB locators, 4-48 connection
using getOracleObject() method, 4-36 closing, 3-10
casting return values, 4-39 from KPRB driver, 3-26
catalog arguments (DatabaseMetaData), 4-116 opening, 3-3
CHAR opening for JDBC OCI driver, 3-6
object, creating, 4-20 opening for JDBC Thin driver, 3-7
CHAR class, 4-19 Properties object, 3-6
conversions with KPRB driver, 5-25 Connection Manager, 3-28, 5-9, 5-10
CHAR columns browser security, 5-20
space padding, 6-7 installing, 5-11
character sets, 4-21 starting, 5-12
conversions with KPRB driver, 5-25 using multiple managers, 5-13
Class.forName method, 3-3 writing the connect string, 5-12
CLASSPATH, specifying, 2-7 connection properties, 4-109
clearDefines() method, 4-105 database, 4-110
client installation, 3-27 defaultBatchValue, 4-110
CLOB defaultRowPrefetch, 4-110
Index-2
password, 4-110 database URL
put() method, 4-110 including userid and password, 3-5
remarksReporting, 4-110 database URL, specifying, 3-4
user, 4-110 DatabaseMetaData calls, 4-116
connections DatabaseMetaData class, 5-28
read-only, 4-116 entry points for applets, 5-18
constants for SQL types, 4-28 datatype classes, 4-7
CREATE DIRECTORY statement datatype mappings, 3-11
for BFILEs, 4-58 datatypes
CREATE TABLE statement Java, 3-11, 3-12
to create BFILE columns, 4-58 Java native, 3-11, 3-12
to create BLOB, CLOB columns, 4-52 JDBC, 3-11, 3-12
create() method JDBC extensions for Oracle SQL datatypes, 3-12
for CustomDatumFactory interface, 4-75 Oracle SQL, 3-11, 3-12
createDescriptor() method, 4-13 DATE class, 4-22
createStatement() method, 4-24 DBMS_LOB package, 4-49
CursorName debugging JDBC programs, 6-9
limitations, 4-115 DEFAULT_CHARSET character set value, 4-21
cursors, 6-7 defaultBatchValue connection property, 4-110
custom Java classes defaultConnection() method, 5-22
defining, 4-65 defaultRowPrefetch connection property, 4-110
custom Java types defineColumnType() method, 3-19, 4-25, 4-106
creating, 7-20, 7-26 dnldthin sub-protocol, 5-8
CustomDatum interface, 4-3 DriverManager class, 3-3
advantages, 4-65 dynamic SQL, 1-2
example program, 7-26
reading data, 4-79
E
writing data, 4-80
encryption
applets, 3-28
D applications, 3-27
data conversions, 4-32 environment variables
LONG, 3-15 specifying, 2-7
LONG RAW, 3-15 error handling and messages, 3-25
data streaming exception trapping, 6-9
avoiding, 3-18 executeBatch() method
example program, 7-2 restrictions on, 4-100
database executeQuery() method, 4-25
connecting executeUpdate() method, 4-101
from an applet, 5-10 extensions to JDBC, Oracle, 4-1
through multiple Connection Managers, 5-13 external file
with KPRB, 5-22 defined, 3-24
connection testing, 2-8
database connection
connection property, 4-110
Index-3
F getColumnType() method, 4-28, 4-44
getColumnTypeName() method, 4-28, 4-44
finalizer methods, 6-7 getConnection() method, 3-4, 4-12, 5-22
firewalls
connection properties, 4-109
configuring for applets, 5-15
for applets, 5-8
connect string, 5-16 getCursor() method, 4-113, 4-114
described, 5-15
getCursorName() method, 4-111
required rule list items, 5-15
limitations, 4-115
using with applets, 3-28, 5-14 getCustomDatum() method, 4-76, 4-79
floating-point compliance, 4-115
getDefaultExecuteBatch() method, 4-24
function call syntax, SQL92 syntax, 5-30
getDefaultRowPrefetch() method, 4-24, 4-98
getDescriptor() method, 4-12
G getDirAlias() method, 4-19, 4-60
getExecuteBatch() method, 4-26, 4-101
getARRAY() method, 4-88
returning current batch value, 4-103
getArray() method, 4-15, 4-88
getMap() method, 4-12
using type maps, 4-90
getName() method, 4-19, 4-60
getArrayDescriptor() method, 4-15
getNumericFunctions() method, 5-28
getAsciiOutputStream() method, 4-18
getObject() method
for writing CLOB data, 4-50
casting return values, 4-39
getAsciiStream() method, 4-18
for BLOBs and CLOBs, 4-46
for reading CLOB data, 4-49
for CustomDatum objects, 4-76
getAttributes() method, 4-11, 4-63
for object references, 4-84
used by Structs, 4-69
for SQLInput streams, 4-70
getBaseName() method, 4-17
for SQLOutput streams, 4-71
getBaseType() method, 4-15, 4-17, 4-92
for Struct objects, 4-64
getBaseTypeName() method, 4-14, 4-15
return types, 4-34, 4-36
used with object references, 4-83
to get BFILE locators, 4-55
getBinaryOutputStream() method, 4-18
to get Oracle objects, 4-63
for writing BLOB data, 4-49
used with CustomDatum interface, 4-80
getBinaryStream() method, 3-17, 4-18, 4-19
getOracleArray() method, 4-15, 4-88, 4-92
for reading BFILE data, 4-57
getOracleAttributes() method, 4-12, 4-64
for reading BLOB data, 4-49
getOracleObject() method, 4-26, 4-27
getBLOB() method, 4-46
casting return values, 4-39
getBytes() method, 3-18, 4-10, 4-18, 4-19
for BLOBs and CLOBs, 4-46
getCharacterOutputStream() method, 4-18
return types, 4-35, 4-36
for writing CLOB data, 4-50
using in callable statement, 4-36
getCharacterStream() method, 4-18
using in result set, 4-35
for reading CLOB data, 4-49
getProcedureColumns() method, 4-108
getChars() method, 4-18
getProcedures() method, 4-108
getChunkSize() method, 4-53
getREF() method, 4-85
getCLOB() method, 4-46
getRemarksReporting() method, 4-25
getColumnCount() method, 4-28
getResultSet() method, 4-15, 4-25
getColumnName() method, 4-28
getRowPrefetch() method, 4-25, 4-98
getColumns() method, 4-108
getSQLTypeName() method, 4-12, 4-15, 4-63, 4-92
Index-4
getString() method, 4-21 stream data, 3-14
to get ROWIDs, 4-111 Java Sockets, 2-2
getStringFunctions() method, 5-28 java.math, Java math packages, 3-2
getStringWithReplacement() method, 4-21 java.sql, JDBC packages, 3-2
getSTRUCT() method, 4-64 java.sql.SQLException() method, 3-25
getSubString() method, 4-19 java.sql.Types class, 4-106
for reading CLOB data, 4-50 java.util.Dictionary class
getSystemFunctions() method, 5-28 used by type maps, 4-67
getTableName() method, 4-28 java.util.Hashtable class
getTimeDateFunctions() method, 5-28 used by type maps, 4-67
getTransactionIsolation() method, 4-24, 6-13 java.util.Map class, 4-91
getTypeMap() method, 4-25, 4-67 JDBC
getValue() method, 4-14 and IDEs, 1-7
for object references, 4-84 and Oracle Application Server, 1-6
getXXX() methods basic program, 3-2
casting return values, 4-39 datatypes, 3-11, 3-12
for specific datatypes, 4-37 defined, 1-2
error handling and messages, 3-25
guidelines for using, 1-3
H
importing packages, 3-2
HEIGHT, parameter for APPLET tag, 5-19 limitations of Oracle extensions, 4-115
HTML tags, to deploy applets, 5-19 Oracle extensions, 1-6
HTTP protocol, 1-5 sample files, 2-7
testing, 2-8
I versions supported, 1-6
JDBC calls, logging, 6-10
IEEE 754 floating-point compliance, 4-115 JDBC drivers
INSERT INTO statement and NLS, 5-2
for creating BFILE columns, 4-59 applets, 3-27
inserts to database, accumulating, 6-6 applications, 3-27
installation basic architecture, 1-4
client, 3-27 choosing a driver for your needs, 2-4
directories and files, 2-6 common features, 2-2
verifying on the client, 2-6 common problems, 6-6
instanceOf() method, 4-35 compatibilities, 2-5
intValue() method, 4-10 determining driver version, 2-8
isConvertableTo() method, 4-12 registering, 3-3
registering for an applet, 5-7
J requirements, 2-5
restrictions, 6-7
Java
SQL92 syntax, 5-26
compiling and running, 2-7 JDBC KPRB driver
datatypes, 3-11, 3-12 architecture, 1-6
native datatypes, 3-11, 3-12
described, 2-4
stored procedures, 3-25 JDBC mapping (for attributes), 4-82
Index-5
JDBC OCI driver getting from callable statements, 4-47
applications, 3-27 passing, 4-47
architecture, 1-5 LOBs
described, 2-3 example program, 7-4
NLS considerations, 5-3 locators
JDBC Thin driver getting for BFILEs, 4-55
applets, 3-27, 5-7 getting for BLOBs, 4-46
applications, 3-27 getting for CLOBs, 4-46
architecture, 1-5 LOB, 4-45
described, 2-2 passing to callable statements, 4-48
NLS considerations, 5-4 passing to prepared statement, 4-48
JdbcCheckup program, 2-8 LONG
JDeveloper, 1-7 data conversions, 3-15
JDK LONG RAW
version considerations, 5-20 data conversions, 3-15
versions supported, 1-6
JPublisher utility, 4-3, 4-65
M
data mapping options, 4-82
using with JDBC, 4-82 makeDatumArray() method, 4-12
memory leaks, 6-7
multi-threaded applications
K on the client, 6-2
KPRB driver
connection string for, 5-23
N
connection to database, 5-22
described, 5-22 named arrays, 4-87
NLS considerations, 5-4 defined, 4-15
relation to the SQL engine, 5-22 National Language Support (NLS), 4-21
session context, 5-23 Net8
support for NLS, 5-25 name-value pair, 3-4
testing, 5-24 protocol, 1-5
transaction context, 5-23 network events, trapping, 6-10
next() method, 4-27
NLS
L and JDBC drivers, 5-2
LD_LIBRARY_PATH variable, specifying, 2-7 conversions, 5-2
length() method, 4-18, 4-19 data size restrictions, 5-5
LIKE escape characters, SQL92 syntax, 5-29 for JDBC OCI drivers, 5-3
limitations, 4-116 for JDBC Thin drivers, 5-4
LOB for KPRB driver, 5-4
defined, 3-23 Java methods that employ, 5-2
locators, 4-45 using, 5-2
reading data, 4-48 NLS Ratio, 5-5
working with, 4-45 NLS_LANG environment variable, 5-3
LOB locators NULL data
Index-6
converting, 4-33 Java classes which support, 4-62
NUMBER class, 4-22 reading data by using SQLData interface, 4-72
working with, 4-62
writing data by using SQLData interface, 4-74
O
Oracle SQL datatypes, 3-11, 3-12
Object JDBC mapping (for attributes), 4-82 Oracle8 Connection Manager, 5-9
object references OracleCallableStatement class, 4-26
accessing object values, 4-84, 4-85 getXXX() methods, 4-37
defined, 4-83 registerOutParameter() method, 4-42
passing to callable statement, 4-85 OracleConnection class, 4-24
passing to prepared statements, 4-86 OracleDatabaseMetaData class, 5-28
redefining columns containing, 4-105 and applets, 5-18
updating object values, 4-84, 4-85 OracleDriver class, 4-24
working with, 4-83 oracle.jdbc2 package, described, 4-6
openFile() method, 4-19 oracle.jdbc2.Struct class, 4-10, 4-63
optimization, performance, 6-5 getAttributes() method, 4-63
Oracle Application Server, 1-6 getSQLTypeName() method, 4-63
Oracle datatypes oracle.jdbc.driver package, 4-22
using, 4-32 stream classes, 4-28
Oracle extensions oracle.jdbc.driver, Oracle JDBC extensions, 3-3
datatype support, 4-2 oracle.jdbc.driver.OracleCallableStatement
limitations, 4-115 class, 4-26
catalog arguments to DatabaseMetaData close() method, 4-27
calls, 4-116 getOracleObject() method, 4-26
CursorName, 4-115 getXXX() methods, 4-26
IEEE 754 floating-point compliance, 4-115 registerOutParameter() method, 4-27
PL/SQL TABLE, BOOLEAN, RECORD setNull() method, 4-27
types, 4-115 setOracleObject() methods, 4-27
read-only connection, 4-116 setXXX() methods, 4-27
SQL92 outer join escapes, 4-115 oracle.jdbc.driver.OracleConnection class, 4-24
SQLWarning class, 4-116 createStatement() method, 4-24
object support, 4-3 getDefaultExecuteBatch() method, 4-24
packages, 4-2 getDefaultRowPrefetch() method, 4-24
performance extensions, 4-97 getRemarksReporting() method, 4-25
result sets, 4-33 getTransactionIsolation() method, 4-24, 6-13
schema naming support, 4-4 getTypeMap() method, 4-25
statements, 4-33 prepareCall() method, 4-24
to JDBC, 4-1 prepareStatement() method, 4-24
Oracle mapping (for attributes), 4-82 setDefaultExecuteBatch() method, 4-24
Oracle objects setDefaultRowPrefetch() method, 4-25
and JDBC, 4-62 setRemarksReporting() method, 4-25
converting with CustomDatum interface, 4-75 setTransactionIsolation() method, 4-24, 6-13
converting with SQLData interface, 4-69 setTypeMap() method, 4-25
defining with Java classes, 4-65 oracle.jdbc.driver.OracleDriver class, 4-24, 5-7
getting with getObject() method, 4-63 oracle.jdbc.driver.OraclePreparedStatement
Index-7
class, 4-25 getBaseTypeName() method, 4-15
close() method, 4-26 getOracleArray() method, 4-15
getExecuteBatch() method, 4-26 getResultSet() method, 4-15
setCustomDatum() method, 4-26 getSQLTypeName() method, 4-15
setExecuteBatch() method, 4-26 oracle.sql.ArrayDescriptor class
setNull() method, 4-26 getBaseName() method, 4-17
setOracleObject() method, 4-26 getBaseType() method, 4-17
setXXX() methods, 4-26 oracle.sql.BFILE class, 4-17
oracle.jdbc.driver.OracleResultSet class, 4-27 closeFile() method, 4-19
getOracleObject() method, 4-27 getBinaryStream() method, 4-19
getXXX() methods, 4-27 getBytes() method, 4-19
next() method, 4-27 getDirAlias() method, 4-19
oracle.jdbc.driver.OracleResultSetMetaData getName() method, 4-19
class, 4-28, 4-44 length() method, 4-19
getColumnCount() method, 4-28 openFile() method, 4-19
getColumnName() method, 4-28 position() method, 4-19
getColumnType() method, 4-28 oracle.sql.BLOB class, 4-17
getColumnTypeName() method, 4-28 getBinaryOutputStream() method, 4-18
getTableName() method, 4-28 getBinaryStream() method, 4-18
using, 4-44 getBytes() method, 4-18
oracle.jdbc.driver.OracleStatement class, 4-25 length() method, 4-18
close() method, 4-25 position() method, 4-18
defineColumnType(), 4-25 putBytes() method, 4-18
executeQuery() method, 4-25 oracle.sql.CHAR class, 4-19, 5-25
getResultSet() method, 4-25 getString() method, 4-21
getRowPrefetch() method, 4-25 getStringWithReplacement() method, 4-21
setRowPrefetch() method, 4-25 toString() method, 4-21
oracle.jdbc.driver.OracleTypes class, 4-28, 4-106 oracle.sql.CharacterSet class, 4-20
OraclePreparedStatement class, 4-25 oracle.sql.CLOB class, 4-17
OracleResultSet class, 4-27 getAsciiOutputStream() method, 4-18
getXXX() methods, 4-37 getAsciiStream() method, 4-18
OracleResultSet object, 3-9 getCharacterOutputStream() method, 4-18
OracleResultSetMetaData class, 4-28 getCharacterStream() method, 4-18
OracleServerDriver class getChars() method, 4-18
defaultConnection() method, 5-22 getSubString() method, 4-19
oracle.sql datatype classes, 4-7 length() method, 4-19
oracle.sql package position() method, 4-19
data conversions, 4-32 putChars() method, 4-19
described, 4-7 putString() method, 4-19
oracle.sql.ARRAY class, 4-87 supported character sets, 4-18
and nested tables, 4-14 oracle.sql.CustomDatum interface, 4-75
and VARRAYs, 4-14 oracle.sql.CustomDatumFactory interface, 4-75
getArray() method, 4-15 oracle.sql.datatypes
getArrayDescriptor() method, 4-15 support, 4-10
getBaseType() method, 4-15 oracle.sql.DATE class, 4-22
Index-8
oracle.sql.Datum class, described, 4-7 PATH variable, specifying, 2-7
oracle.sql.NUMBER class, 4-22 performance extensions
OracleSql.parse() method, 5-30 batching updates, 4-100
oracle.sql.RAW class, 4-22 connection properties, 4-109
oracle.sql.REF class, 4-14, 4-83 prefetching rows, 4-98
getBaseTypeName() method, 4-14 redefining column types, 4-105
getValue() method, 4-14 TABLE_REMARKS reporting, 4-108
setValue() method, 4-14 to JDBC, 4-97
oracle.sql.REFCURSOR class, 4-112 performance optimization, 6-5
oracle.sql.ROWID class, 4-10, 4-22, 4-111 batching values, 6-6
oracle.sql.STRUCT class, 4-10, 4-63 prefetching rows, 6-6
getConnection() method, 4-12 PL/SQL
getDescriptor() method, 4-12 restrictions, 6-7
getMap() method, 4-12 space padding, 6-7
getOracleAttributes() method, 4-12 stored procedures, 3-24
getSQLTypeName() method, 4-12 PL/SQL stored procedures, 3-24
isConvertibleTo() method, 4-12 PL/SQL types
makeJdbcArray() method, 4-12 limitations, 4-115
methods, 4-11 position() method, 4-18, 4-19
getAttributes() method, 4-11 prefetching rows, 4-97, 4-98, 6-6
setDatumArray() method, 4-12 suggested default, 4-98
setDescriptor() method, 4-12 prepareCall() method, 4-24
stringValue() method, 4-12 prepared statement
toBytes() method, 4-12 passing BFILE locator, 4-56
toClass() method, 4-12 passing LOB locators, 4-48
toJDBC() method, 4-12 using setObject() method, 4-41
toSTRUCT() method, 4-12 using setOracleObject() method, 4-41
oracle.sql.StructDescriptor class, 4-13 prepareStatement() method, 4-24
createDescriptor() method, 4-13 printStackTrace() method, 6-9
OracleStatement class, 4-25 put() method
OracleTypes class, 4-28 for Properties object, 4-110
OracleTypes.ARRAY class, 4-28, 4-44 for type maps, 4-67
OracleTypes.BFILE class, 4-29 putBytes() method, 4-18
OracleTypes.BLOB class, 4-28 putChars() method, 4-19
OracleTypes.CLOB class, 4-28 putString() method, 4-19
OracleTypes.CURSOR variable, 4-113
OracleTypes.REF class, 4-28
Q
OracleTypes.ROWID class, 4-29
OracleTypes.STRUCT class, 4-28, 4-44 query, executing, 3-8
outer joins, SQL92 syntax, 5-29
R
P RAW class, 4-22
password connection property, 4-110 readSQL() method, 4-69, 4-70
password, specifying, 3-4 implementing, 4-70
Index-9
REF class, 4-14 setAutoCommit() method, 6-5
REFCURSORs, 4-112 setBFILE() method, 4-56
example program, 7-14 setBLOB() method, 4-47
materialized as result set objects, 4-112 setCLOB() method, 4-48
reference classes, and JPublisher, 4-83 setCursorName() method, 4-111, 4-115
registerDriver() method, 4-24 setCustomDatum() method, 4-26, 4-77, 4-81
registering Oracle JDBC drivers, class for, 4-24 setDatumArray() method, 4-12
registerOutParameter() method, 4-27, 4-42 setDefaultExecuteBatch() method, 4-24
remarksReporting connection property, 4-110 setDefaultRowPrefetch() method, 4-25, 4-98
remarksReporting flag, 4-97 setDescriptor() method, 4-12
result set setEscapeProcessing() method, 5-26
auto-commit mode, 6-5 setExecuteBatch() method, 4-26
getting BFILE locators, 4-55 setLogStream() method, for logging JDBC
getting LOB locators, 4-46 calls, 6-10
metadata, 4-28 setMaxFieldSize() method, 4-106, 6-7
Oracle extensions, 4-33 setNull() method, 4-26, 4-27, 4-42
using getOracleObject() method, 4-35 setObejct() method, 4-40
result set object setObject() method
closing, 3-9 for BFILES, 4-56
result set, processing, 3-9 for BLOBs and CLOBs, 4-47
ResultSet class, 3-8 for CustomDatum objects, 4-77
return types for object references, 4-86
for getXXX() methods, 4-38 to write object data, 4-81
getObject() method, 4-36 using in prepared statements, 4-41
getOracleObject() method, 4-36 setOracleObject() method, 4-26, 4-27, 4-40
return values for BFILES, 4-56
casting, 4-39 for BLOBs and CLOBs, 4-47
ROLLBACK operation, 5-24 for Struct objects, 4-64
row prefetching, 4-98 using in prepared statements, 4-41
and data streams, 3-23 setREF() method, 4-86
ROWID class, 4-22 setRemarksReporting() method, 4-25, 4-108
CursorName methods, 4-115 setRowPrefetch() method, 4-25, 4-98
defined, 4-111 setString() method
to bind ROWIDs, 4-111
setTransactionIsolation() method, 4-24, 6-13
S
setTypeMap() method, 4-25, 4-68
scalar functions, SQL92 syntax, 5-28 setValue() method, 4-14
schema naming conventions, 4-4 setXXX() methods, for specific datatypes, 4-41
security, for browsers, 5-20 signed applets, 3-28
SELECT statement SQL
to retrieve object references, 4-84 data converting to Java datatypes, 4-32
to select LOB locator, 4-54 primitive types, 4-7
sendBatch() method, 4-102 structured types, 4-7
session context, 3-26 types, constants for, 4-28
for KPRB driver, 5-23 SQL engine
Index-10
relation to the KPRB driver, 5-22 LOBs, 3-23
SQL syntax (Oracle), 5-26 LONG columns, 3-14
SQL92 syntax, 5-26 LONG RAW columns, 3-14
function call syntax, 5-30 multiple columns, 3-20
LIKE escape characters, 5-29 RAW columns, 3-19
outer joins, 5-29 row prefetching, 3-23
scalar functions, 5-28 UPDATE/COMMIT statements, 4-50
time and date literals, 5-26 VARCHAR columns, 3-19
translating to SQL example, 5-30 stream data column
SQLData interface, 4-3 bypassing, 3-21
advantages, 4-66 stringValue() method, 4-10, 4-12
described, 4-69 STRUCT class, 4-10
example program, 7-20 STRUCT descriptor, 4-13
Oracle implementation, 4-6 STRUCT object, 4-10
reading data from Oracle objects, 4-72 attributes, 4-11
using with type map, 4-69 casting, 4-63
writing data from Oracle objects, 4-74 creating, 4-13
SQLException() method, 6-9 embedded object, 4-14
SQLInput interface, 4-69 nested objects, 4-11
described, 4-70 using, 4-63
SQLInput streams, 4-70 StructDescriptor object
SQLJ creating, 4-13
advantages over JDBC, 1-3 get methods, 4-13
guidelines for using, 1-3 structured objects, 4-9
SQLNET.ORA class for binding, 4-26
parameters for tracing, 6-10
SQLOutput interface, 4-69
T
described, 4-70
SQLOutput streams, 4-71 TABLE_REMARKS columns, 4-97
SQLWarning class, limitations, 4-116 TABLE_REMARKS reporting
Statement object restrictions on, 4-108
closing, 3-9 TCP/IP protocol, 1-5, 3-7
creating, 3-8 time and date literals, SQL92 syntax, 5-26
statements TNSNAMES entries, 3-4
Oracle extensions, 4-33 toBytes() method, 4-12
static SQL, 1-2 toClass() method, 4-12
stored procedures toDatum() method
Java, 3-25 applied to CustomDatum objects, 4-65, 4-75
PL/SQL, 3-24 called by setCustomDatum() method, 4-81
stream classes, 4-28 toJDBC() method, 4-12
stream data, 3-14, 4-48 toJdbc() method, 4-10
CHAR columns, 3-19 toString() method, 4-21
closing, 3-23 toSTRUCT() method, 4-12
example, 3-16 trace facility, 6-10
external files, 3-23 trace parameters
Index-11
client-side, 6-11
server-side, 6-12
transaction context, 3-26
for KPRB driver, 5-23
TTC protocol, 1-5
type map, 4-3, 4-34, 4-65
adding entries, 4-67
and STRUCTs, 4-69
creating a new map, 4-68
defining mappings, 4-67
described, 4-66
used with arrays, 4-91
used with SQLData interface, 4-69
using with arrays, 4-94
type maps
relationship to database connection, 5-23
U
updates to database, accumulating, 6-6
user connection property, 4-110
userid, specifying, 3-4
using, 5-10
V
VARCHAR2 columns, 6-7
varrays
example program, 7-16
W
WIDTH, parameter for APPLET tag, 5-19
writeSQL() method, 4-69, 4-71
implementing, 4-70
Index-12