JDBC 4.0 and Oracle JDeveloper for J2EE Development
上QQ阅读APP看书,第一时间看更新

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

Enhancements in SQLException

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 Management

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:

if(stmt.isPoolable())
stmt.setPoolable(true);

Scalar Functions

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: