📄 oraclelobhandler.java
字号:
/*
* Copyright 2002-2004 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.lob;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
import org.springframework.util.FileCopyUtils;
/**
* LobHandler implementation for Oracle databases. Uses proprietary API to
* create oracle.sql.BLOB and oracle.sql.CLOB instances, as necessary when
* working with Oracle's JDBC driver. Developed and tested on Oracle 9i.
*
* <p>While most databases are able to work with DefaultLobHandler, Oracle just
* accepts Blob/Clob instances created via its own proprietary BLOB/CLOB API,
* and additionally doesn't accept large streams for PreparedStatement's
* corresponding setter methods. Therefore, you need to use a strategy like
* this LobHandler implementation.
*
* <p>Needs to work on a native JDBC Connection, to be able to cast it to
* oracle.jdbc.OracleConnection. If you pass in Connections from a connection
* pool (the usual case in a J2EE environment), you need to set an appropriate
* NativeJdbcExtractor to allow for automatical retrieval of the underlying
* native JDBC Connection. LobHandler and NativeJdbcExtractor are separate
* concerns, therefore they are represented by separate strategy interfaces.
*
* <p>Coded via reflection to avoid dependencies on Oracle classes.
* Even reads in Oracle constants via reflection because of different Oracle
* drivers (classes12, ojdbc14) having different constant values!
* As it initializes the Oracle classes on instantiation, do not define this
* as eager-initializing singleton if you do not want to depend on the Oracle
* JAR being in the class path: use "lazy-init=true" to avoid this issue.
*
* @author Juergen Hoeller
* @since 04.12.2003
* @see #setNativeJdbcExtractor
* @see oracle.sql.BLOB
* @see oracle.sql.CLOB
*/
public class OracleLobHandler implements LobHandler {
private static final String CONNECTION_CLASS_NAME = "oracle.jdbc.OracleConnection";
private static final String BLOB_CLASS_NAME = "oracle.sql.BLOB";
private static final String CLOB_CLASS_NAME = "oracle.sql.CLOB";
private static final String DURATION_SESSION_FIELD_NAME = "DURATION_SESSION";
private static final String MODE_READWRITE_FIELD_NAME = "MODE_READWRITE";
protected final Log logger = LogFactory.getLog(getClass());
private final Class connectionClass;
private final Class blobClass;
private final Class clobClass;
private final Map durationSessionConstants = new HashMap(2);
private final Map modeReadWriteConstants = new HashMap(2);
private NativeJdbcExtractor nativeJdbcExtractor;
private Boolean cache = Boolean.TRUE;
/**
* This constructor retrieves the oracle.sql.BLOB and oracle.sql.CLOB
* classes via reflection, and initializes the values for the
* DURATION_SESSION and MODE_READWRITE constants defined there.
* @see oracle.sql.BLOB#DURATION_SESSION
* @see oracle.sql.BLOB#MODE_READWRITE
* @see oracle.sql.CLOB#DURATION_SESSION
* @see oracle.sql.CLOB#MODE_READWRITE
*/
public OracleLobHandler() {
try {
this.connectionClass = getClass().getClassLoader().loadClass(CONNECTION_CLASS_NAME);
// initialize oracle.sql.BLOB class
this.blobClass = getClass().getClassLoader().loadClass(BLOB_CLASS_NAME);
this.durationSessionConstants.put(
this.blobClass, new Integer(this.blobClass.getField(DURATION_SESSION_FIELD_NAME).getInt(null)));
this.modeReadWriteConstants.put(
this.blobClass, new Integer(this.blobClass.getField(MODE_READWRITE_FIELD_NAME).getInt(null)));
// initialize oracle.sql.CLOB class
this.clobClass = getClass().getClassLoader().loadClass(CLOB_CLASS_NAME);
this.durationSessionConstants.put(
this.clobClass, new Integer(this.clobClass.getField(DURATION_SESSION_FIELD_NAME).getInt(null)));
this.modeReadWriteConstants.put(
this.clobClass, new Integer(this.clobClass.getField(MODE_READWRITE_FIELD_NAME).getInt(null)));
}
catch (Exception ex) {
throw new InvalidDataAccessApiUsageException(
"Couldn't initialize OracleLobHandler because Oracle driver classes are not available", ex);
}
}
/**
* Set an appropriate NativeJdbcExtractor to be able to retrieve the underlying
* native oracle.jdbc.OracleConnection. This is necessary for DataSource-based
* connection pools, as those need to return wrapped JDBC Connection handles.
* <p>Effectively, this LobHandler just invokes a single NativeJdbcExtractor
* method, namely <code>getNativeConnectionFromStatement</code> with a
* PreparedStatement argument (falling back to a
* <code>PreparedStatement.getConnection()</code> call if no extractor is set).
* <p>A common choice is SimpleNativeJdbcExtractor, whose Connection unwrapping
* (which is what OracleLobHandler needs) will work with almost any connection
* pool. See SimpleNativeJdbcExtractor's javadoc for details.
* @see org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor#getNativeConnectionFromStatement
* @see org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor
* @see oracle.jdbc.OracleConnection
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.nativeJdbcExtractor = nativeJdbcExtractor;
}
/**
* Set whether to cache the temporary LOB in the buffer cache.
* This value will be passed into BLOB/CLOB.createTemporary. Default is true.
* @see oracle.sql.BLOB#createTemporary
* @see oracle.sql.CLOB#createTemporary
*/
public void setCache(boolean cache) {
this.cache = new Boolean(cache);
}
public byte[] getBlobAsBytes(ResultSet rs, int columnIndex) throws SQLException {
logger.debug("Returning BLOB as bytes");
Blob blob = rs.getBlob(columnIndex);
return (blob != null ? blob.getBytes(1, (int) blob.length()) : null);
}
public InputStream getBlobAsBinaryStream(ResultSet rs, int columnIndex) throws SQLException {
logger.debug("Returning BLOB as binary stream");
Blob blob = rs.getBlob(columnIndex);
return (blob != null ? blob.getBinaryStream() : null);
}
public String getClobAsString(ResultSet rs, int columnIndex) throws SQLException {
logger.debug("Returning CLOB as string");
Clob clob = rs.getClob(columnIndex);
return (clob != null ? clob.getSubString(1, (int) clob.length()) : null);
}
public InputStream getClobAsAsciiStream(ResultSet rs, int columnIndex) throws SQLException {
logger.debug("Returning CLOB as ASCII stream");
Clob clob = rs.getClob(columnIndex);
return (clob != null ? clob.getAsciiStream() : null);
}
public Reader getClobAsCharacterStream(ResultSet rs, int columnIndex) throws SQLException {
logger.debug("Returning CLOB as character stream");
Clob clob = rs.getClob(columnIndex);
return (clob != null ? clob.getCharacterStream() : null);
}
public LobCreator getLobCreator() {
return new OracleLobCreator();
}
/**
* LobCreator implementation for Oracle databases.
* Creates Oracle-style temporary BLOBs and CLOBs that it frees on close.
* @see #close
*/
protected class OracleLobCreator implements LobCreator {
private final List createdLobs = new LinkedList();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -