diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java
index a885565259..9085bde167 100644
--- a/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java
+++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java
@@ -54,7 +54,6 @@ import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
-import java.sql.SQLOutput;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
@@ -81,22 +80,10 @@ class DefaultBindContext extends AbstractBindContext {
/**
* Generated UID
*/
- private static final long serialVersionUID = -5457385919209241505L;
- private static final JooqLogger log = JooqLogger.getLogger(DefaultBindContext.class);
+ private static final long serialVersionUID = -5457385919209241505L;
+ private static final JooqLogger log = JooqLogger.getLogger(DefaultBindContext.class);
- /**
- * The localConfiguration is used to communicate a Configuration to an
- * {@link ArrayRecord}, in case that ArrayRecord is serialised to a
- * {@link SQLOutput} object.
- *
- * This is probably the only solution to circumvent this bad JDBC design.
- * See also http://stackoverflow
- * .com/q/11439543/521799
- */
- static final ThreadLocal LOCAL_CONFIGURATION = new ThreadLocal();
-
- private final PreparedStatement stmt;
+ private final PreparedStatement stmt;
DefaultBindContext(Configuration configuration, PreparedStatement stmt) {
super(configuration);
@@ -305,15 +292,7 @@ class DefaultBindContext extends AbstractBindContext {
stmt.setString(nextIndex(), ((EnumType) value).getLiteral());
}
else {
- try {
- // [#1544] Set the local configuration, in case an array needs
- // to be serialised to SQLOutput
- LOCAL_CONFIGURATION.set(this);
- stmt.setObject(nextIndex(), value);
- }
- finally {
- LOCAL_CONFIGURATION.remove();
- }
+ stmt.setObject(nextIndex(), value);
}
return this;
diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java
index 1568a2a37d..e9f088a6f4 100644
--- a/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java
+++ b/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java
@@ -37,9 +37,11 @@ package org.jooq.impl;
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.sql.SQLOutput;
import java.util.ArrayList;
import java.util.List;
@@ -93,7 +95,9 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
private static final ThreadLocal> CLOBS = new ThreadLocal>();
/**
- * Clean up blobs and clobs.
+ * Clean up blobs, clobs and the local configuration.
+ *
+ *
BLOBS and CLOBS
*
* [#1326] This is necessary in those dialects that have long-lived
* temporary lob objects, which can cause memory leaks in certain contexts,
@@ -106,6 +110,22 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
*
Not freeing the lob after execution will cause an
* {@link OutOfMemoryError}
*
+ *
+ *
Local configuration
+ *
+ * [#1544] There exist some corner-cases regarding the {@link SQLOutput}
+ * API, used for UDT serialisation / deserialisation, which have no elegant
+ * solutions of obtaining a {@link Configuration} and thus a JDBC
+ * {@link Connection} object short of:
+ *
+ * - Making assumptions about the JDBC driver and using proprietary API,
+ * e.g. that of ojdbc
+ * - Dealing with this problem globally by using such a local
+ * configuration
+ *
+ *
+ * @see http://stackoverflow.com/q/11439543/521799
*/
static final void clean() {
List blobs = BLOBS.get();
@@ -126,6 +146,8 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
CLOBS.remove();
}
+
+ LOCAL_CONFIGURATION.remove();
}
/**
@@ -142,6 +164,30 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
CLOBS.get().add(clob);
}
+ // ------------------------------------------------------------------------
+ // XXX: Static utility methods for handling Configuration lifecycle
+ // ------------------------------------------------------------------------
+
+ private static final ThreadLocal LOCAL_CONFIGURATION = new ThreadLocal();
+
+ /**
+ * Register a configuration for later cleanup with {@link #clean()}
+ */
+ static final void register(Configuration configuration) {
+ LOCAL_CONFIGURATION.set(configuration);
+ }
+
+ /**
+ * Get the registered configuration
+ *
+ * It can be safely assumed that such a configuration is available once the
+ * {@link ExecuteContext} has been established, until the statement is
+ * closed.
+ */
+ static final Configuration registeredConfiguration() {
+ return LOCAL_CONFIGURATION.get();
+ }
+
// ------------------------------------------------------------------------
// XXX: Constructors
// ------------------------------------------------------------------------
@@ -182,6 +228,7 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
clean();
BLOBS.set(new ArrayList());
CLOBS.set(new ArrayList());
+ LOCAL_CONFIGURATION.set(configuration);
}
@Override
diff --git a/jOOQ/src/main/java/org/jooq/impl/Executor.java b/jOOQ/src/main/java/org/jooq/impl/Executor.java
index 091afd3874..77dbd9cfcf 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Executor.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Executor.java
@@ -160,7 +160,6 @@ public class Executor implements FactoryOperations {
private static final long serialVersionUID = 2681360188806309513L;
private static final JooqLogger log = JooqLogger.getLogger(Factory.class);
- private static final Executor[] DEFAULT_INSTANCES = new Executor[SQLDialect.values().length];
private final Configuration configuration;
// -------------------------------------------------------------------------
@@ -1558,19 +1557,6 @@ public class Executor implements FactoryOperations {
return configuration.toString();
}
- static {
- for (SQLDialect dialect : SQLDialect.values()) {
- DEFAULT_INSTANCES[dialect.ordinal()] = new Executor(dialect);
- }
- }
-
- /**
- * Get a default Factory without a {@link Connection}
- */
- final static Executor getNewFactory(SQLDialect dialect) {
- return getNewFactory(DEFAULT_INSTANCES[dialect.ordinal()]);
- }
-
/**
* Get a default Factory with a {@link Connection}
*/
diff --git a/jOOQ/src/main/java/org/jooq/impl/FieldTypeHelper.java b/jOOQ/src/main/java/org/jooq/impl/FieldTypeHelper.java
index 00f04e89ff..426bce24c0 100644
--- a/jOOQ/src/main/java/org/jooq/impl/FieldTypeHelper.java
+++ b/jOOQ/src/main/java/org/jooq/impl/FieldTypeHelper.java
@@ -346,7 +346,7 @@ public final class FieldTypeHelper {
// [#1544] We can safely assume that localConfiguration has been
// set on DefaultBindContext, prior to serialising arrays to SQLOut
- Connection connection = getDriverConnection(DefaultBindContext.LOCAL_CONFIGURATION.get());
+ Connection connection = getDriverConnection(DefaultExecuteContext.registeredConfiguration());
ArrayRecord> arrayRecord = (ArrayRecord>) value;
stream.writeArray(on(connection).call("createARRAY", arrayRecord.getName(), arrayRecord.get()).get());
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/UDTRecordImpl.java b/jOOQ/src/main/java/org/jooq/impl/UDTRecordImpl.java
index 650277f578..c6e812d4ba 100644
--- a/jOOQ/src/main/java/org/jooq/impl/UDTRecordImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/UDTRecordImpl.java
@@ -76,7 +76,7 @@ public class UDTRecordImpl> extends AbstractRecord implem
// [#1693] This needs to return the fully qualified SQL type name, in
// case the connected user is not the owner of the UDT
- Configuration configuration = DefaultBindContext.LOCAL_CONFIGURATION.get();
+ Configuration configuration = DefaultExecuteContext.registeredConfiguration();
if (configuration != null) {
Schema schema = Util.getMappedSchema(configuration, getUDT().getSchema());
@@ -92,10 +92,8 @@ public class UDTRecordImpl> extends AbstractRecord implem
@Override
public final void readSQL(SQLInput stream, String typeName) throws SQLException {
- Executor configuration = Executor.getNewFactory(getUDT().getDataType().getDialect());
-
for (Field> field : getUDT().getFields()) {
- setValue(configuration, stream, field);
+ setValue(DefaultExecuteContext.registeredConfiguration(), stream, field);
}
}