[#1161] Use reflection to remove compile-time dependency on ojdbc for creating ARRAYs
This commit is contained in:
parent
5561e3b071
commit
396f999fb7
@ -197,13 +197,6 @@
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.oracle</groupId>
|
||||
<artifactId>ojdbc6</artifactId>
|
||||
<version>11.1.0.7.0</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
||||
@ -35,6 +35,9 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static org.jooq.impl.Util.getDriverConnection;
|
||||
import static org.jooq.tools.reflect.Reflect.on;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
@ -50,7 +53,6 @@ import org.jooq.DataType;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.exception.SQLDialectNotSupportedException;
|
||||
import org.jooq.tools.Convert;
|
||||
import org.jooq.util.oracle.OracleUtils;
|
||||
|
||||
/**
|
||||
* A common base class for Oracle ARRAY types
|
||||
@ -180,8 +182,10 @@ public class ArrayRecordImpl<T> extends AbstractStore<T> implements ArrayRecord<
|
||||
SQLDialect dialect = getConfiguration().getDialect();
|
||||
|
||||
switch (dialect) {
|
||||
case ORACLE:
|
||||
return OracleUtils.createArray(getConfiguration().getConnection(), this);
|
||||
case ORACLE: {
|
||||
// [#1161] Use reflection to avoid compile-time on ojdbc
|
||||
return on(getDriverConnection(getConfiguration())).call("createARRAY", getName(), get()).get();
|
||||
}
|
||||
|
||||
default:
|
||||
throw new SQLDialectNotSupportedException(
|
||||
|
||||
@ -74,6 +74,10 @@ class ConnectionProxy implements Connection {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
final Connection getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// XXX Creation of PreparedStatements
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@ -244,7 +244,15 @@ public class Factory implements FactoryOperations {
|
||||
*/
|
||||
@Override
|
||||
public final Connection getConnection() {
|
||||
return (connection == null ? null : new ConnectionProxy(connection, settings));
|
||||
if (connection == null) {
|
||||
return null;
|
||||
}
|
||||
else if (connection.getClass() == ConnectionProxy.class) {
|
||||
return connection;
|
||||
}
|
||||
else {
|
||||
return new ConnectionProxy(connection, settings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -42,6 +42,7 @@ import static org.jooq.tools.StringUtils.leftPad;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
@ -93,7 +94,7 @@ final class Util {
|
||||
/**
|
||||
* Create a new Oracle-style VARRAY {@link ArrayRecord}
|
||||
*/
|
||||
static <R extends ArrayRecord<?>> R newArrayRecord(Class<R> type, Configuration configuration) {
|
||||
static final <R extends ArrayRecord<?>> R newArrayRecord(Class<R> type, Configuration configuration) {
|
||||
try {
|
||||
return type.getConstructor(Configuration.class).newInstance(configuration);
|
||||
}
|
||||
@ -108,28 +109,28 @@ final class Util {
|
||||
/**
|
||||
* Create a new record
|
||||
*/
|
||||
static <R extends Record> R newRecord(Class<R> type) {
|
||||
static final <R extends Record> R newRecord(Class<R> type) {
|
||||
return newRecord(type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new record
|
||||
*/
|
||||
static <R extends Record> R newRecord(Class<R> type, FieldProvider provider) {
|
||||
static final <R extends Record> R newRecord(Class<R> type, FieldProvider provider) {
|
||||
return newRecord(type, provider, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new record
|
||||
*/
|
||||
static <R extends Record> R newRecord(Type<R> type) {
|
||||
static final <R extends Record> R newRecord(Type<R> type) {
|
||||
return newRecord(type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new record
|
||||
*/
|
||||
static <R extends Record> R newRecord(Type<R> type, Configuration configuration) {
|
||||
static final <R extends Record> R newRecord(Type<R> type, Configuration configuration) {
|
||||
return newRecord(type.getRecordType(), type, configuration);
|
||||
}
|
||||
|
||||
@ -137,7 +138,7 @@ final class Util {
|
||||
* Create a new record
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static <R extends Record> R newRecord(Class<R> type, FieldProvider provider, Configuration configuration) {
|
||||
static final <R extends Record> R newRecord(Class<R> type, FieldProvider provider, Configuration configuration) {
|
||||
try {
|
||||
R result;
|
||||
|
||||
@ -301,7 +302,7 @@ final class Util {
|
||||
/**
|
||||
* Create SQL
|
||||
*/
|
||||
static void toSQLReference(RenderContext context, String sql, List<Param<?>> bindings) {
|
||||
static final void toSQLReference(RenderContext context, String sql, List<Param<?>> bindings) {
|
||||
|
||||
// Replace bind variables by their associated bind values
|
||||
if (context.inline()) {
|
||||
@ -352,7 +353,7 @@ final class Util {
|
||||
/**
|
||||
* Create {@link Param} objects from bind values
|
||||
*/
|
||||
static List<Param<?>> bindings(Object... bindings) {
|
||||
static final List<Param<?>> bindings(Object... bindings) {
|
||||
// [#724] When bindings is null, this is probably due to API-misuse
|
||||
// The user probably meant new Object[] { null }
|
||||
if (bindings == null) {
|
||||
@ -375,7 +376,7 @@ final class Util {
|
||||
*
|
||||
* @see #toSQLReference(RenderContext, String, List)
|
||||
*/
|
||||
static void toSQLReferenceWithParentheses(RenderContext context, String sql, List<Param<?>> bindings) {
|
||||
static final void toSQLReferenceWithParentheses(RenderContext context, String sql, List<Param<?>> bindings) {
|
||||
context.sql("(");
|
||||
toSQLReference(context, sql, bindings);
|
||||
context.sql(")");
|
||||
@ -385,7 +386,7 @@ final class Util {
|
||||
* Render a list of names of the <code>NamedQueryParts</code> contained in
|
||||
* this list.
|
||||
*/
|
||||
static void toSQLNames(RenderContext context, Collection<? extends NamedQueryPart> list) {
|
||||
static final void toSQLNames(RenderContext context, Collection<? extends NamedQueryPart> list) {
|
||||
String separator = "";
|
||||
|
||||
for (NamedQueryPart part : list) {
|
||||
@ -398,7 +399,7 @@ final class Util {
|
||||
/**
|
||||
* Combine a field with an array of fields
|
||||
*/
|
||||
static Field<?>[] combine(Field<?> field, Field<?>... fields) {
|
||||
static final Field<?>[] combine(Field<?> field, Field<?>... fields) {
|
||||
if (fields == null) {
|
||||
return new Field[] { field };
|
||||
}
|
||||
@ -414,7 +415,7 @@ final class Util {
|
||||
/**
|
||||
* Combine a field with an array of fields
|
||||
*/
|
||||
static Field<?>[] combine(Field<?> field1, Field<?> field2, Field<?>... fields) {
|
||||
static final Field<?>[] combine(Field<?> field1, Field<?> field2, Field<?>... fields) {
|
||||
if (fields == null) {
|
||||
return new Field[] { field1, field2 };
|
||||
}
|
||||
@ -431,7 +432,7 @@ final class Util {
|
||||
/**
|
||||
* Combine a field with an array of fields
|
||||
*/
|
||||
static Field<?>[] combine(Field<?> field1, Field<?> field2, Field<?> field3, Field<?>... fields) {
|
||||
static final Field<?>[] combine(Field<?> field1, Field<?> field2, Field<?> field3, Field<?>... fields) {
|
||||
if (fields == null) {
|
||||
return new Field[] { field1, field2, field3 };
|
||||
}
|
||||
@ -448,7 +449,7 @@ final class Util {
|
||||
/**
|
||||
* Translate a {@link SQLException} to a {@link DataAccessException}
|
||||
*/
|
||||
static DataAccessException translate(String task, String sql, SQLException e) {
|
||||
static final DataAccessException translate(String task, String sql, SQLException e) {
|
||||
String message = task + "; SQL [" + sql + "]; " + e.getMessage();
|
||||
return new DataAccessException(message, e);
|
||||
}
|
||||
@ -456,7 +457,7 @@ final class Util {
|
||||
/**
|
||||
* Safely close a statement
|
||||
*/
|
||||
static void safeClose(Statement statement) {
|
||||
static final void safeClose(Statement statement) {
|
||||
if (statement != null) {
|
||||
try {
|
||||
statement.close();
|
||||
@ -468,7 +469,7 @@ final class Util {
|
||||
/**
|
||||
* Safely close a result set
|
||||
*/
|
||||
static void safeClose(ResultSet resultSet) {
|
||||
static final void safeClose(ResultSet resultSet) {
|
||||
if (resultSet != null) {
|
||||
try {
|
||||
resultSet.close();
|
||||
@ -480,7 +481,7 @@ final class Util {
|
||||
/**
|
||||
* Safely close a cursor
|
||||
*/
|
||||
static void safeClose(Cursor<?> cursor) {
|
||||
static final void safeClose(Cursor<?> cursor) {
|
||||
if (cursor != null) {
|
||||
try {
|
||||
cursor.close();
|
||||
@ -492,15 +493,41 @@ final class Util {
|
||||
/**
|
||||
* Safely close a result set and / or a statement
|
||||
*/
|
||||
static void safeClose(ResultSet resultSet, PreparedStatement statement) {
|
||||
static final void safeClose(ResultSet resultSet, PreparedStatement statement) {
|
||||
safeClose(resultSet);
|
||||
safeClose(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract an underlying connection
|
||||
*/
|
||||
static final Connection getDriverConnection(Configuration configuration) {
|
||||
if (configuration != null) {
|
||||
Connection connection = configuration.getConnection();
|
||||
|
||||
if (connection != null) {
|
||||
|
||||
// If the connection is wrapped by jOOQ, extract the underlying
|
||||
// connection
|
||||
if (connection.getClass() == ConnectionProxy.class) {
|
||||
connection = ((ConnectionProxy) connection).getDelegate();
|
||||
}
|
||||
|
||||
// [#1157] TODO: If jOOQ's extended tracing / logging feature
|
||||
// allows for further wrapping a connection, this must be
|
||||
// treated here...
|
||||
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
|
||||
throw new DataAccessException("Cannot get a JDBC driver connection from configuration: " + configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if JPA classes can be loaded. This is only done once per JVM!
|
||||
*/
|
||||
private static boolean isJPAAvailable() {
|
||||
private static final boolean isJPAAvailable() {
|
||||
if (isJPAAvailable == null) {
|
||||
try {
|
||||
Class.forName(Column.class.getName());
|
||||
@ -764,7 +791,7 @@ final class Util {
|
||||
* Map a {@link Schema} according to the configured {@link org.jooq.SchemaMapping}
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
static Schema getMappedSchema(Configuration configuration, Schema schema) {
|
||||
static final Schema getMappedSchema(Configuration configuration, Schema schema) {
|
||||
if (configuration.getSchemaMapping() != null) {
|
||||
return configuration.getSchemaMapping().map(schema);
|
||||
}
|
||||
@ -777,7 +804,7 @@ final class Util {
|
||||
* Map a {@link Table} according to the configured {@link org.jooq.SchemaMapping}
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
static Table<?> getMappedTable(Configuration configuration, Table<?> table) {
|
||||
static final Table<?> getMappedTable(Configuration configuration, Table<?> table) {
|
||||
if (configuration.getSchemaMapping() != null) {
|
||||
return configuration.getSchemaMapping().map(table);
|
||||
}
|
||||
@ -789,7 +816,7 @@ final class Util {
|
||||
/**
|
||||
* Wrap a piece of SQL code in parentheses, if not wrapped already
|
||||
*/
|
||||
static String wrapInParentheses(String sql) {
|
||||
static final String wrapInParentheses(String sql) {
|
||||
if (sql.startsWith("(")) {
|
||||
return sql;
|
||||
}
|
||||
@ -801,14 +828,14 @@ final class Util {
|
||||
/**
|
||||
* Expose the internal API of an {@link Attachable}
|
||||
*/
|
||||
static AttachableInternal internal(Attachable part) {
|
||||
static final AttachableInternal internal(Attachable part) {
|
||||
return part.internalAPI(AttachableInternal.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the internal API of a {@link QueryPart}
|
||||
*/
|
||||
static QueryPartInternal internal(QueryPart part) {
|
||||
static final QueryPartInternal internal(QueryPart part) {
|
||||
return part.internalAPI(QueryPartInternal.class);
|
||||
}
|
||||
|
||||
@ -816,7 +843,7 @@ final class Util {
|
||||
* Return a non-negative hash code for a {@link QueryPart}, taking into
|
||||
* account FindBugs' <code>RV_ABSOLUTE_VALUE_OF_HASHCODE</code> pattern
|
||||
*/
|
||||
static int hash(Object object) {
|
||||
static final int hash(Object object) {
|
||||
return 0x7FFFFFF & object.hashCode();
|
||||
}
|
||||
|
||||
@ -827,7 +854,7 @@ final class Util {
|
||||
/**
|
||||
* Get the statement type from the settings
|
||||
*/
|
||||
static StatementType getStatementType(Settings settings) {
|
||||
static final StatementType getStatementType(Settings settings) {
|
||||
if (settings != null) {
|
||||
Execution execution = settings.getExecution();
|
||||
|
||||
@ -856,7 +883,7 @@ final class Util {
|
||||
* @param value the byte array
|
||||
* @return the hex encoded string
|
||||
*/
|
||||
static String convertBytesToHex(byte[] value) {
|
||||
static final String convertBytesToHex(byte[] value) {
|
||||
return convertBytesToHex(value, value.length);
|
||||
}
|
||||
|
||||
@ -867,7 +894,7 @@ final class Util {
|
||||
* @param len the number of bytes to encode
|
||||
* @return the hex encoded string
|
||||
*/
|
||||
static String convertBytesToHex(byte[] value, int len) {
|
||||
static final String convertBytesToHex(byte[] value, int len) {
|
||||
char[] buff = new char[len + len];
|
||||
char[] hex = HEX;
|
||||
for (int i = 0; i < len; i++) {
|
||||
@ -881,7 +908,7 @@ final class Util {
|
||||
/**
|
||||
* Postgres uses octals instead of hex encoding
|
||||
*/
|
||||
static String convertBytesToPostgresOctal(byte[] binary) {
|
||||
static final String convertBytesToPostgresOctal(byte[] binary) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (byte b : binary) {
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2011, Lukas Eder, lukas.eder@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed to you under the Apache License, Version 2.0
|
||||
* (the "License"); You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* . Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* . Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* . Neither the name "jOOQ" nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.util.oracle;
|
||||
|
||||
import java.sql.Array;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import oracle.sql.ARRAY;
|
||||
import oracle.sql.ArrayDescriptor;
|
||||
|
||||
import org.jooq.ArrayRecord;
|
||||
import org.jooq.SQLDialect;
|
||||
|
||||
/**
|
||||
* Utility methods for use with {@link SQLDialect#ORACLE}
|
||||
* <p>
|
||||
* This class has a hidden dependency on the Oracle JDBC driver. Be sure that
|
||||
* these classes and all of their dependencies are located on the classpath:
|
||||
* <ul>
|
||||
* <li>{@link ArrayDescriptor}</li>
|
||||
* <li>{@link ARRAY}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public final class OracleUtils {
|
||||
|
||||
/**
|
||||
* Create an Oracle {@link ARRAY}
|
||||
*/
|
||||
public static Array createArray(Connection connection, ArrayRecord<?> record) throws SQLException {
|
||||
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor(record.getName(), connection);
|
||||
return new ARRAY(descriptor, connection, record.get());
|
||||
}
|
||||
|
||||
private OracleUtils() {}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user