OPENJPA-2067: Added code, gated by the new DBDictionary.useJDBC4SetBinaryStream prop, to use a JDBC 4.0 version of setBinaryStream.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/branches/2.0.x@1337557 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Heath Thomann 2012-05-12 14:54:39 +00:00
parent 5fd2b4fe28
commit 8052dfd4ee
3 changed files with 67 additions and 3 deletions

View File

@ -28,6 +28,7 @@ import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Array;
@ -51,7 +52,6 @@ import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -66,10 +66,10 @@ import javax.sql.DataSource;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.identifier.ColumnDefIdentifierRule;
import org.apache.openjpa.jdbc.identifier.Normalizer;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.identifier.DBIdentifierRule;
import org.apache.openjpa.jdbc.identifier.DBIdentifierUtil;
import org.apache.openjpa.jdbc.identifier.Normalizer;
import org.apache.openjpa.jdbc.identifier.DBIdentifier.DBIdentifierType;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
@ -88,7 +88,6 @@ import org.apache.openjpa.jdbc.schema.Index;
import org.apache.openjpa.jdbc.schema.NameSet;
import org.apache.openjpa.jdbc.schema.PrimaryKey;
import org.apache.openjpa.jdbc.schema.Schema;
import org.apache.openjpa.jdbc.schema.SchemaGroup;
import org.apache.openjpa.jdbc.schema.Sequence;
import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.jdbc.schema.Unique;
@ -103,6 +102,7 @@ import org.apache.openjpa.lib.identifier.IdentifierConfiguration;
import org.apache.openjpa.lib.identifier.IdentifierRule;
import org.apache.openjpa.lib.identifier.IdentifierUtil;
import org.apache.openjpa.lib.jdbc.ConnectionDecorator;
import org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement;
import org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
@ -288,6 +288,7 @@ public class DBDictionary
public boolean useGetObjectForBlobs = false;
public boolean useGetStringForClobs = false;
public boolean useSetStringForClobs = false;
public boolean useJDBC4SetBinaryStream = false;//OPENJPA-2067
public int maxEmbeddedBlobSize = -1;
public int maxEmbeddedClobSize = -1;
public int inClauseLimit = -1;
@ -396,6 +397,11 @@ public class DBDictionary
// 0 = no batch
// any positive number = batch limit
public int batchLimit = NO_BATCH;
/**
* Set when we reflectively find a JDBC 4.0 version of the 'setBinaryStream' method.
*/
Method _setBinaryStream = null;
public final Map<Integer,Set<String>> sqlStateCodes =
new HashMap<Integer, Set<String>>();
@ -927,6 +933,39 @@ public class DBDictionary
public void setBinaryStream(PreparedStatement stmnt, int idx,
InputStream val, int length, Column col)
throws SQLException {
//OPENJPA-2067: If the user has set the 'useJDBC4SetBinaryStream' property
//then an attempt will be made, using reflections, to obtain the necessary
//setBinaryStream method.
if (useJDBC4SetBinaryStream) {
try {
if (_setBinaryStream == null) {
_setBinaryStream = PreparedStatement.class.getMethod(
"setBinaryStream", int.class, InputStream.class);
}
//If here, the necessary 'setBinaryStream' method exists so call it now.
PreparedStatement inner = stmnt;
PreparedStatement outer = stmnt;
if (stmnt instanceof DelegatingPreparedStatement) {
inner = (PreparedStatement) ((DelegatingPreparedStatement)stmnt).getInnermostDelegate();
outer = (PreparedStatement) ((DelegatingPreparedStatement)stmnt).getDelegate();
}
_setBinaryStream.invoke(inner, new Object[] { idx, val } );
// Direct invocation of setClob on the Oracle driver bypasses OpenJPA's built-in
// parameter logging via decorators. Log the parameter directly.
LoggingConnectionDecorator.logStatementParameter(outer, idx, "setBinaryStream", val);
return;
} catch (Throwable t) {
//If we didn't find the proper setBinaryStream method, lets set
//'useJDBC4SetBinaryStream' to false to avoid lots of message
//warnings.
useJDBC4SetBinaryStream=false;
log.warn(_loc.get("jdbc4-setbinarystream-unsupported"), t);
}
}
stmnt.setBinaryStream(idx, val, length);
}

View File

@ -223,4 +223,8 @@ oracle-set-clob-failed: Invocation of methods to support storing large character
large object (CLOB) or XML values did not complete successfully. An \
alternate method is used to store the data; however, if the data is larger \
than 4000 bytes, data, an error might occur.
jdbc4-setbinarystream-unsupported: The JRE or JDBC level in use does not support the \
JDBC 4.0 version of the "java.sql.PreparedStatement.setBinaryStream" method which is \
necessary when the property "openjpa.jdbc.DBDictionary=useJDBC4SetBinaryStream=true" is \
set. A prior version of this method will be used.

View File

@ -3301,6 +3301,27 @@ ResultSet.getString</methodname> will be used to obtain clob data rather than
<methodname>ResultSet.getCharacterStream</methodname>.
</para>
</listitem>
<listitem id="DBDictionary.UseJDBC4SetBinaryStream">
<para>
<indexterm>
<primary>
JDBC
</primary>
<secondary>
UseJDBC4SetBinaryStream
</secondary>
</indexterm>
<literal>UseJDBC4SetBinaryStream</literal>: When true, an attempt will be made to obtain
a JDBC 4.0 version of <methodname>PreparedStatement.setBinaryStream</methodname>.
By default a <methodname>setBinaryStream</methodname> is used which takes the length of the
stream. OpenJPA uses a -1 for the length since OpenJPA doesn't know the length of the stream.
A few JDBC drivers check the length and throw an exception when the length is less than zero.
When this property is set to true, and an applicable JDK and JDBC 4.0 driver is available, a
version of <methodname>setBinaryStream</methodname> will be used which does not take a length.
The default value of this property is false.
</para>
</listitem>
<listitem id="DBDictionary.UseNativeSequenceCache">
<para>
<indexterm>