[#1895] Decouple Executor from Configuration. Use composition rather
than inheritance - Removed Executor.DEFAULT_INSTANCES, remainders of early jOOQ days
This commit is contained in:
parent
16be60c44a
commit
36c98e4cc4
@ -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.
|
||||
* <p>
|
||||
* This is probably the only solution to circumvent this bad JDBC design.
|
||||
* See also <a
|
||||
* href="http://stackoverflow.com/q/11439543/521799">http://stackoverflow
|
||||
* .com/q/11439543/521799</a>
|
||||
*/
|
||||
static final ThreadLocal<Configuration> LOCAL_CONFIGURATION = new ThreadLocal<Configuration>();
|
||||
|
||||
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;
|
||||
|
||||
@ -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<List<Clob>> CLOBS = new ThreadLocal<List<Clob>>();
|
||||
|
||||
/**
|
||||
* Clean up blobs and clobs.
|
||||
* Clean up blobs, clobs and the local configuration.
|
||||
* <p>
|
||||
* <h3>BLOBS and CLOBS</h3>
|
||||
* <p>
|
||||
* [#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
|
||||
* <li>Not freeing the lob after execution will cause an
|
||||
* {@link OutOfMemoryError}</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* <h3>Local configuration</h3>
|
||||
* <p>
|
||||
* [#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:
|
||||
* <ul>
|
||||
* <li>Making assumptions about the JDBC driver and using proprietary API,
|
||||
* e.g. that of ojdbc</li>
|
||||
* <li>Dealing with this problem globally by using such a local
|
||||
* configuration</li>
|
||||
* </ul>
|
||||
*
|
||||
* @see <a
|
||||
* href="http://stackoverflow.com/q/11439543/521799">http://stackoverflow.com/q/11439543/521799</a>
|
||||
*/
|
||||
static final void clean() {
|
||||
List<Blob> 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<Configuration> LOCAL_CONFIGURATION = new ThreadLocal<Configuration>();
|
||||
|
||||
/**
|
||||
* Register a configuration for later cleanup with {@link #clean()}
|
||||
*/
|
||||
static final void register(Configuration configuration) {
|
||||
LOCAL_CONFIGURATION.set(configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the registered configuration
|
||||
* <p>
|
||||
* 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<Blob>());
|
||||
CLOBS.set(new ArrayList<Clob>());
|
||||
LOCAL_CONFIGURATION.set(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -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 <code>Factory</code> without a {@link Connection}
|
||||
*/
|
||||
final static Executor getNewFactory(SQLDialect dialect) {
|
||||
return getNewFactory(DEFAULT_INSTANCES[dialect.ordinal()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a default <code>Factory</code> with a {@link Connection}
|
||||
*/
|
||||
|
||||
@ -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()).<Array>get());
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ public class UDTRecordImpl<R extends UDTRecord<R>> 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<R extends UDTRecord<R>> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user