
Support for Wrapper Pattern
Some vendor-specific JDBC resources that provide nonstandard JDBC methods are wrapped for architectural reasons. Such JDBC resources can be unwrapped to access instances with the wrapper pattern. Support for wrapper pattern is implemented in the Wrapper
interface. With the Wrapper
interface, resources that are wrapped as proxy classes can be accessed. The objective of the Wrapper
interface is to provide a standard method to access vendor-specific extensions inside standard JDBC objects, such as, Connections, Statements
, and ResultSets
. The Wrapper
interface is extended by the following interfaces:
- java.sql.Connection
- java.sql.DataSource
- java.sql.ResultSet
- java.sql.Statement
- java.sql.DatabaseMetaData
- java.sql.ResultSetMetaData
- java.sql.ParameterMetaData
The Wrapper
interface provides the methods isWrapperFor(Class<?>)
and unwrap(Class<?>)
. The unwrap()
method takes an interface as a parameter, and returns an Object
that implements the interface. The object that is returned is either the object found to implement the specified interface, or a proxy for that object. The isWrapperFor()
method returns a boolean
. This method is used to find out if an instance implements the specified interface, or if an instance is a wrapper for an object that implements the specified interface. If the object implements the specified interface the value returned is true
. If the object is a wrapper for the specified interface, the isWrapperFor()method
is invoked recursively on the wrapped object. If the object does not implement the interface and is not a wrapper for the interface, the value returned is false
. The unwrap()
method should be invoked, if the isWrapperFor()
method returns true
.
Create an object of type, java.sql.PreparedStatement
and check if the object is a wrapper for the Oracle JDBC specific interface, oracle.jdbc.OraclePreparedStatement
using the isWrapperFor()
method. If the object is a wrapper for the interface, create an instance of the oracle.jdbc.OraclePreparedStatement
JDBC interface using the unwrap()
method:
String url="jdbc:oracle:thin:@localhost:1521:ORCL"; Connection connection = DriverManager.getConnection(url,"oe", "pw"); String sql="INSERT INTO CATALOG(catalogId, journal) VALUES(?,?)" java.sql.PreparedStatement stmt = connection.prepareStatement(sql); Class class = Class.forName("oracle.jdbc.OraclePreparedStatement"); if(stmt.isWrapperFor(class)) { OraclePreparedStatement ops = (OraclePreparedStatement)stmt.unwrap(class); ops.defineColumnType(2, oracle.jdbc.OracleTypes.VARCHAR,4000); }
An error in interaction with the datasource is represented with the SQLException
class. JDBC 4.0 has enhanced support for navigation of chained SQLExceptions
with the iterator()
method in the SQLException
class. A chained SQLException
is an Exception
that is linked with other Exceptions
. The iterator()
method iterates over the chained exceptions and the chained causes. Chained exceptions can be retrieved and iterated over (without having to invoke the getNextException()
and getCause()
methods recursively) using the enhanced For-Each loop introduced in J2SE 5. When an SQLException
is generated using the For-Each loop, the chained exceptions can be output as shown below:
catch(SQLException sqlException) { for(Throwable e : sqlException ) { System.out.println("Error encountered: " + e); } }
In JDBC 4.0, four constructors have been added to the SQLException
class with the Throwable cause
as one of the parameters. The getCause()
method can return non-SQLExceptions
. In JDBC 4.0, three new categories of SQLExceptions
have been added, which are as follows:
- SQLTransientException
- SQLNonTransientException
- SQLRecoverableException
Categorization of the SQLExceptions
facilitates the portability of error handling code. SQLTransientException
and SQLNonTransientException
classes have subclasses, which map to common SQLState
class values. SQLState
class provides JDBC application's return code information about the most recently executed SQL statement. The return code is sent by the database manager after the completion of each SQL statement. The SQLState
class values are defined in the SQL: 2003 specification.
A SQLTransientException
indicates that the operation that generates the exception could succeed, if retried. Subclasses of the SQLTransientException
class are discussed in following table:

SQLNonTransientException
indicates the operation, which generates the exception that will not succeed without the cause of the SQLException
being rectified. Subclasses of the SQLNonTransientException
are discussed in following table:

The SQLRecoverableException
indicates that the operation that throws the Exception
can succeed, if the application performs some recovery steps and retries the entire transaction(or the transaction branch in the case of a distributed transaction). The recovery steps include at the least, closing the current connection and obtaining a new connection.
A new subclass of the SQLException
class, SQLClientInfoException
, has been added in the JDBC 4.0 specification. The SQLClientInfoException
is generated, if one or more client info properties could not be set on a Connection
. The SQLClientInfoException
also lists the client info properties, which were not set. Some databases that do not allow multiple client info properties to be set atomically can generate the SQLClientInfoException
exception after one or more client info properties have been set. The client info properties that were not set can be retrieved by using the getFailedProperties()
method.
Connection pooling improves the performance and scalability of the connections by providing a cache of the connections that are reusable across client sessions. Connection pooling reduces the overhead of opening, initializing and closing connections. One of the drawbacks of the connection pooling is that when a connection in a connection pool becomes stale and unusable, the application performance is reduced. JDBC 3.0 specification did not have the provision to track connection state. Connection state tracking has been added to the Connection
interface in the JDBC 4.0 to find out if a connection is valid. The isValid(int timeout)
method returns true, if the connection is valid. The isValid()
method validates a connection with a SQL query, or another mechanism. If a connection is not valid, the connection can be closed, thus reducing the accumulation of unusable connections. The Connection
object conn
can be closed, if it is not in use:
if(!conn.isClosed()) if(!conn.isValid()) conn.close();
Connection state tracking and closing of invalid connections are implemented by the connection pool manager. Another drawback of connection pooling has been that one or more connections assigned from a connection pool in a web or application server can bog down an application. JDBC 3.0 does not have the provision to identify the connections that use the excess of CPU time. JDBC 4.0 has added the setClientInfo()
and getClientInfo()
methods to the Connection
interface using which, client specific information can be specified on a Connection
object, when a Connection
is assigned to an application. Client specification information includes user name and application name. The DatabaseMetaData
interface in JDBC 4.0 provides a new method, getClientInfoProperties()
. Client info properties supported by a JDBC driver can be obtained using the getClientInfoProperties()
method. When one or more connections bog down the application, the getClientInfo()
method can be used to identify which connections could be causing the reduction in performance. Some standard client info properties that a JDBC driver can support are discussed in the following table:

Similar to connection pooling, JDBC 4.0 provides Statement
pooling to reduce the overheads of opening, initiating, and closing Statement
objects. Frequently used Statement
objects can be pooled using the setPoolable(boolean poolable)
method. The isPoolable()
method is used to check if a Statement
object is poolable. The Statement
object, stmt
can be pooled, if poolable:
Most databases support numeric, string, time, date, system, and conversion functions on the scalar values. SQL statements run using the Statement
object, and can include the scalar functions using the JDBC escape syntax. JDBC 4.0 provides some new scalar function, which are discussed in the following table:
