Browse Source

added configurable Connection/Statement/ResultSet target types to Jdbc4NativeJdbcExtractor (SPR-7613); added OracleJdbc4NativeJdbcExtractor with pre-configured Oracle JDBC API types

pull/1234/head
Juergen Hoeller 15 years ago
parent
commit
ccded10d86
  1. 38
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/lob/OracleLobHandler.java
  2. 71
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/Jdbc4NativeJdbcExtractor.java
  3. 60
      org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/OracleJdbc4NativeJdbcExtractor.java
  4. 1
      org.springframework.jdbc/template.mf

38
org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/lob/OracleLobHandler.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -122,6 +122,7 @@ public class OracleLobHandler extends AbstractLobHandler { @@ -122,6 +122,7 @@ public class OracleLobHandler extends AbstractLobHandler {
* See SimpleNativeJdbcExtractor's javadoc for details.
* @see org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor#getNativeConnectionFromStatement
* @see org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor
* @see org.springframework.jdbc.support.nativejdbc.OracleJdbc4NativeJdbcExtractor
* @see oracle.jdbc.OracleConnection
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
@ -144,20 +145,16 @@ public class OracleLobHandler extends AbstractLobHandler { @@ -144,20 +145,16 @@ public class OracleLobHandler extends AbstractLobHandler {
* Set whether to agressively release any resources used by the LOB. If set to <code>true</code>
* then you can only read the LOB values once. Any subsequent reads will fail since the resources
* have been closed.
*
* <p>Setting this property to <code>true</code> can be useful when your queries generates large
* temporary LOBs that occupy space in the TEMPORARY tablespace or when you want to free up any
* memory allocated by the driver for the LOB reading.
*
* <p>Default is <code>false</code>.
*
* @see oracle.sql.BLOB#freeTemporary
* @see oracle.sql.CLOB#freeTemporary
* @see oracle.sql.BLOB#open
* @see oracle.sql.CLOB#open
* @see oracle.sql.BLOB#close
* @see oracle.sql.CLOB#close
* @since 3.0
*/
public void setReleaseResourcesAfterRead(boolean releaseResources) {
this.releaseResourcesAfterRead = releaseResources;
@ -258,27 +255,25 @@ public class OracleLobHandler extends AbstractLobHandler { @@ -258,27 +255,25 @@ public class OracleLobHandler extends AbstractLobHandler {
/**
* Initialize any LOB resources before a read is done.
*
* <p>This implementation calls
* <code>BLOB.open(BLOB.MODE_READONLY)</code> or <code>CLOB.open(CLOB.MODE_READONLY)</code>
* on any non-temporary LOBs
* if <code>releaseResourcesAfterRead</code> property is set to <code>true</code>.
* <p>This implementation calls <code>BLOB.open(BLOB.MODE_READONLY)</code> or
* <code>CLOB.open(CLOB.MODE_READONLY)</code> on any non-temporary LOBs if
* <code>releaseResourcesAfterRead</code> property is set to <code>true</code>.
* <p>This method can be overridden by sublcasses if different behavior is desired.
* @param con the connection to be usde for initilization
* @param lob the LOB to initialize
*/
protected void initializeResourcesBeforeRead(Connection con, Object lob) {
if (releaseResourcesAfterRead) {
if (this.releaseResourcesAfterRead) {
initOracleDriverClasses(con);
try {
/*
if (!((BLOB)lob.isTemporary() {
if (!((BLOB) lob.isTemporary() {
*/
Method isTemporary = lob.getClass().getMethod("isTemporary");
Boolean temporary = (Boolean) isTemporary.invoke(lob);
if (!temporary) {
/*
((BLOB)lob).open(BLOB.MODE_READONLY);
((BLOB) lob).open(BLOB.MODE_READONLY);
*/
Method open = lob.getClass().getMethod("open", int.class);
open.invoke(lob, modeReadOnlyConstants.get(lob.getClass()));
@ -295,44 +290,42 @@ public class OracleLobHandler extends AbstractLobHandler { @@ -295,44 +290,42 @@ public class OracleLobHandler extends AbstractLobHandler {
/**
* Release any LOB resources after read is complete.
*
* <p>If <code>releaseResourcesAfterRead</code> property is set to <code>true</code>
* then this implementation calls
* <code>BLOB.close()</code> or <code>CLOB.close()</code>
* on any non-temporary LOBs that are open or
* <code>BLOB.freeTemporary()</code> or <code>CLOB.freeTemporary()</code>
* on any temporary LOBs.
*
* <p>This method can be overridden by sublcasses if different behavior is desired.
* @param con the connection to be usde for initilization
* @param lob the LOB to initialize
*/
protected void releaseResourcesAfterRead(Connection con, Object lob) {
if (releaseResourcesAfterRead) {
if (this.releaseResourcesAfterRead) {
initOracleDriverClasses(con);
Boolean temporary = Boolean.FALSE;
try {
/*
if (((BLOB)lob.isTemporary() {
if (((BLOB) lob.isTemporary() {
*/
Method isTemporary = lob.getClass().getMethod("isTemporary");
temporary = (Boolean) isTemporary.invoke(lob);
if (temporary) {
/*
((BLOB)lob).freeTemporary();
((BLOB) lob).freeTemporary();
*/
Method freeTemporary = lob.getClass().getMethod("freeTemporary");
freeTemporary.invoke(lob);
}
else {
/*
if (((BLOB)lob.isOpen() {
if (((BLOB) lob.isOpen() {
*/
Method isOpen = lob.getClass().getMethod("isOpen");
Boolean open = (Boolean) isOpen.invoke(lob);
if (open) {
/*
((BLOB)lob).close();
((BLOB) lob).close();
*/
Method close = lob.getClass().getMethod("close");
close.invoke(lob);
@ -358,6 +351,7 @@ public class OracleLobHandler extends AbstractLobHandler { @@ -358,6 +351,7 @@ public class OracleLobHandler extends AbstractLobHandler {
}
}
/**
* LobCreator implementation for Oracle databases.
* Creates Oracle-style temporary BLOBs and CLOBs that it frees on close.
@ -529,8 +523,8 @@ public class OracleLobHandler extends AbstractLobHandler { @@ -529,8 +523,8 @@ public class OracleLobHandler extends AbstractLobHandler {
protected Connection getOracleConnection(PreparedStatement ps)
throws SQLException, ClassNotFoundException {
return (nativeJdbcExtractor != null) ?
nativeJdbcExtractor.getNativeConnectionFromStatement(ps) : ps.getConnection();
return (nativeJdbcExtractor != null ?
nativeJdbcExtractor.getNativeConnectionFromStatement(ps) : ps.getConnection());
}
/**

71
org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/Jdbc4NativeJdbcExtractor.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -26,10 +26,16 @@ import java.sql.Statement; @@ -26,10 +26,16 @@ import java.sql.Statement;
/**
* {@link NativeJdbcExtractor} implementation that delegates to JDBC 4.0's
* <code>unwrap</code> method, as defined by {@link java.sql.Wrapper}.
* You will typically need to specify a vendor {@link #setConnectionType Connection type}
* / {@link #setStatementType Statement type} / {@link #setResultSetType ResultSet type}
* to extract, since JDBC 4.0 only actually unwraps to a given target type.
*
* <p>Note: Only use this when actually running against a JDBC 4.0 driver,
* with a connection pool that supports the JDBC 4.0 API (i.e. at least accepts
* JDBC 4.0 API calls and passes them through to the underlying driver)!
* <p>Note: Only use this when actually running against a JDBC 4.0 driver, with a
* connection pool that supports the JDBC 4.0 API (i.e. at least accepts JDBC 4.0
* API calls and passes them through to the underlying driver)! Other than that,
* there is no need for connection pool specific setup. As of JDBC 4.0,
* NativeJdbcExtractors will typically be implemented for specific drivers
* instead of for specific pools (e.g. {@link OracleJdbc4NativeJdbcExtractor}).
*
* @author Juergen Hoeller
* @since 2.5
@ -40,29 +46,76 @@ import java.sql.Statement; @@ -40,29 +46,76 @@ import java.sql.Statement;
*/
public class Jdbc4NativeJdbcExtractor extends NativeJdbcExtractorAdapter {
private Class<? extends Connection> connectionType = Connection.class;
private Class<? extends Statement> statementType = Statement.class;
private Class<? extends PreparedStatement> preparedStatementType = PreparedStatement.class;
private Class<? extends CallableStatement> callableStatementType = CallableStatement.class;
private Class<? extends ResultSet> resultSetType = ResultSet.class;
/**
* Set the vendor's Connection type, e.g. <code>oracle.jdbc.OracleConnection</code>.
*/
public void setConnectionType(Class<? extends Connection> connectionType) {
this.connectionType = connectionType;
}
/**
* Set the vendor's Statement type, e.g. <code>oracle.jdbc.OracleStatement</code>.
*/
public void setStatementType(Class<? extends Statement> statementType) {
this.statementType = statementType;
}
/**
* Set the vendor's PreparedStatement type, e.g. <code>oracle.jdbc.OraclePreparedStatement</code>.
*/
public void setPreparedStatementType(Class<? extends PreparedStatement> preparedStatementType) {
this.preparedStatementType = preparedStatementType;
}
/**
* Set the vendor's CallableStatement type, e.g. <code>oracle.jdbc.OracleCallableStatement</code>.
*/
public void setCallableStatementType(Class<? extends CallableStatement> callableStatementType) {
this.callableStatementType = callableStatementType;
}
/**
* Set the vendor's ResultSet type, e.g. <code>oracle.jdbc.OracleResultSet</code>.
*/
public void setResultSetType(Class<? extends ResultSet> resultSetType) {
this.resultSetType = resultSetType;
}
@Override
protected Connection doGetNativeConnection(Connection con) throws SQLException {
return (Connection) con.unwrap(Connection.class);
return con.unwrap(this.connectionType);
}
@Override
public Statement getNativeStatement(Statement stmt) throws SQLException {
return (Statement) stmt.unwrap(Statement.class);
return stmt.unwrap(this.statementType);
}
@Override
public PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException {
return (PreparedStatement) ps.unwrap(PreparedStatement.class);
return ps.unwrap(this.preparedStatementType);
}
@Override
public CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException {
return (CallableStatement) cs.unwrap(CallableStatement.class);
return cs.unwrap(this.callableStatementType);
}
@Override
public ResultSet getNativeResultSet(ResultSet rs) throws SQLException {
return (ResultSet) rs.unwrap(ResultSet.class);
return rs.unwrap(this.resultSetType);
}
}

60
org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/OracleJdbc4NativeJdbcExtractor.java

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.support.nativejdbc;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* A {@link Jdbc4NativeJdbcExtractor} which comes pre-configured for Oracle's JDBC driver,
* specifying the following vendor-specific API types for unwrapping:
* <ul>
* <li><code>oracle.jdbc.OracleConnection</code>
* <li><code>oracle.jdbc.OracleStatement</code>
* <li><code>oracle.jdbc.OraclePreparedStatement</code>
* <li><code>oracle.jdbc.OracleCallableStatement</code>
* <li><code>oracle.jdbc.OracleResultSet</code>
* </ul>
*
* <p>Note: This will work with any JDBC 4.0 compliant connection pool, without a need for
* connection pool specific setup. In other words, as of JDBC 4.0, NativeJdbcExtractors
* will typically be implemented for specific drivers instead of for specific pools.
*
* @author Juergen Hoeller
* @since 3.0.5
*/
public class OracleJdbc4NativeJdbcExtractor extends Jdbc4NativeJdbcExtractor {
@SuppressWarnings("unchecked")
public OracleJdbc4NativeJdbcExtractor() {
try {
setConnectionType((Class<Connection>) getClass().getClassLoader().loadClass("oracle.jdbc.OracleConnection"));
setStatementType((Class<Statement>) getClass().getClassLoader().loadClass("oracle.jdbc.OracleStatement"));
setPreparedStatementType((Class<PreparedStatement>) getClass().getClassLoader().loadClass("oracle.jdbc.OraclePreparedStatement"));
setCallableStatementType((Class<CallableStatement>) getClass().getClassLoader().loadClass("oracle.jdbc.OracleCallableStatement"));
setResultSetType((Class<ResultSet>) getClass().getClassLoader().loadClass("oracle.jdbc.OracleResultSet"));
}
catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize OracleJdbc4NativeJdbcExtractor because Oracle API classes are not available: " + ex);
}
}
}

1
org.springframework.jdbc/template.mf

@ -5,6 +5,7 @@ Bundle-ManifestVersion: 2 @@ -5,6 +5,7 @@ Bundle-ManifestVersion: 2
Import-Package:
com.ibm.websphere.rsadapter;version="0";resolution:=optional,
com.ibm.ws.rsadapter.jdbc;version="0";resolution:=optional,
oracle.jdbc;version="0";resolution:=optional,
oracle.sql;version="0";resolution:=optional,
org.h2;version="[1.8.0, 2.0.0)";resolution:=optional,
org.hsqldb;version="[1.0.0, 2.0.0)";resolution:=optional,

Loading…
Cancel
Save