[#2388] Replace Configuration's List<ExecuteListener> with an
ExecuteListenerProvider to simplify correct and thread-safe client implementations
This commit is contained in:
parent
d104467645
commit
c3883d2b92
@ -59,6 +59,7 @@ import org.jooq.Configuration;
|
||||
import org.jooq.DAO;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.ForeignKey;
|
||||
import org.jooq.Record;
|
||||
@ -707,18 +708,26 @@ public abstract class BaseTest<
|
||||
return delegate.getCastableDataTypes();
|
||||
}
|
||||
|
||||
protected DSLContext create(Settings settings) {
|
||||
protected final DSLContext create(Settings settings) {
|
||||
DSLContext create = delegate.create(settings);
|
||||
create.configuration().getExecuteListeners().add(new TestStatisticsListener());
|
||||
addListeners(create.configuration(), new TestStatisticsListener());
|
||||
return create;
|
||||
}
|
||||
|
||||
protected final DSLContext create(Configuration configuration) {
|
||||
DSLContext create = DSL.using(configuration);
|
||||
create.configuration().getExecuteListeners().add(new TestStatisticsListener());
|
||||
addListeners(create.configuration(), new TestStatisticsListener());
|
||||
return create;
|
||||
}
|
||||
|
||||
protected final List<ExecuteListener> getListeners(Configuration configuration) {
|
||||
return delegate.getListeners(configuration);
|
||||
}
|
||||
|
||||
protected final void addListeners(Configuration configuration, ExecuteListener... listeners) {
|
||||
delegate.addListeners(configuration, listeners);
|
||||
}
|
||||
|
||||
protected final Connection getConnection() {
|
||||
return delegate.getConnection();
|
||||
}
|
||||
|
||||
@ -38,11 +38,10 @@ package org.jooq.test._.testcases;
|
||||
import java.sql.Date;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.Record2;
|
||||
import org.jooq.Record3;
|
||||
@ -51,7 +50,6 @@ import org.jooq.Result;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.TableRecord;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.impl.DefaultConfiguration;
|
||||
import org.jooq.test.BaseTest;
|
||||
import org.jooq.test.jOOQAbstractTest;
|
||||
import org.jooq.tools.StopWatch;
|
||||
@ -128,9 +126,9 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
// This benchmark is contributed by "jjYBdx4IL" on GitHub:
|
||||
// https://github.com/jOOQ/jOOQ/issues/1625
|
||||
|
||||
DefaultConfiguration configuration = new DefaultConfiguration(create().configuration());
|
||||
Configuration configuration = create().configuration().derive();
|
||||
configuration.getSettings().setExecuteLogging(false);
|
||||
configuration.setExecuteListeners(new ArrayList<ExecuteListener>());
|
||||
getListeners(configuration).clear();
|
||||
DSLContext create = create(configuration);
|
||||
|
||||
// Dry-run to avoid side-effects
|
||||
|
||||
@ -53,8 +53,8 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.Cursor;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.ExecuteType;
|
||||
@ -101,7 +101,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
@Test
|
||||
public void testExecuteListenerWithData() throws Exception {
|
||||
DSLContext create = create();
|
||||
create.configuration().getExecuteListeners().add(new DataListener());
|
||||
addListeners(create.configuration(), new DataListener());
|
||||
|
||||
create.selectOne().fetch();
|
||||
}
|
||||
@ -211,7 +211,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
@Test
|
||||
public void testExecuteListenerCustomException() throws Exception {
|
||||
DSLContext create = create();
|
||||
create.configuration().getExecuteListeners().add(new CustomExceptionListener());
|
||||
addListeners(create.configuration(), new CustomExceptionListener());
|
||||
|
||||
try {
|
||||
create.fetch("invalid sql");
|
||||
@ -237,7 +237,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
@Test
|
||||
public void testExecuteListenerOnResultQuery() throws Exception {
|
||||
DSLContext create = create();
|
||||
create.configuration().getExecuteListeners().add(new ResultQueryListener());
|
||||
addListeners(create.configuration(), new ResultQueryListener());
|
||||
|
||||
create.configuration().setData("Foo", "Bar");
|
||||
create.configuration().setData("Bar", "Baz");
|
||||
@ -581,7 +581,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
jOOQAbstractTest.reset = false;
|
||||
|
||||
DSLContext create = create();
|
||||
create.configuration().getExecuteListeners().add(new BatchSingleListener());
|
||||
addListeners(create.configuration(), new BatchSingleListener());
|
||||
|
||||
create.configuration().setData("Foo", "Bar");
|
||||
create.configuration().setData("Bar", "Baz");
|
||||
@ -795,7 +795,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
jOOQAbstractTest.reset = false;
|
||||
|
||||
DSLContext create = create();
|
||||
create.configuration().getExecuteListeners().add(new BatchMultipleListener());
|
||||
addListeners(create.configuration(), new BatchMultipleListener());
|
||||
|
||||
create.configuration().setData("Foo", "Bar");
|
||||
create.configuration().setData("Bar", "Baz");
|
||||
@ -1021,7 +1021,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
@Test
|
||||
public void testExecuteListenerFetchLazyTest() throws Exception {
|
||||
DSLContext create = create();
|
||||
create.configuration().getExecuteListeners().add(new FetchLazyListener());
|
||||
addListeners(create.configuration(), new FetchLazyListener());
|
||||
FetchLazyListener.reset();
|
||||
|
||||
create.selectFrom(TAuthor()).fetch();
|
||||
|
||||
@ -233,7 +233,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
ConnectionProviderListener.c = create().configuration().getConnectionProvider().acquire();
|
||||
try {
|
||||
DSLContext create = create();
|
||||
create.configuration().getExecuteListeners().add(new ConnectionProviderListener());
|
||||
addListeners(create.configuration(), new ConnectionProviderListener());
|
||||
q = create
|
||||
.selectFrom(TAuthor())
|
||||
.orderBy(TAuthor_LAST_NAME());
|
||||
|
||||
@ -51,8 +51,8 @@ import java.sql.PreparedStatement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.Cursor;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.Record2;
|
||||
@ -100,7 +100,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
@Test
|
||||
public void testKeepStatement() throws Exception {
|
||||
DSLContext create = create();
|
||||
create.configuration().getExecuteListeners().add(new KeepStatementListener());
|
||||
addListeners(create.configuration(), new KeepStatementListener());
|
||||
|
||||
// [#385] By default, new statements are created for every execution
|
||||
KeepStatementListener.reset();
|
||||
|
||||
@ -66,6 +66,7 @@ import org.jooq.ArrayRecord;
|
||||
import org.jooq.DAO;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.ExecuteType;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.ForeignKey;
|
||||
@ -90,6 +91,7 @@ import org.jooq.debug.Debugger;
|
||||
import org.jooq.debug.console.Console;
|
||||
import org.jooq.debug.impl.DebuggerFactory;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.DefaultExecuteListenerProvider;
|
||||
import org.jooq.test._.LifecycleWatcherListener;
|
||||
import org.jooq.test._.PrettyPrinter;
|
||||
import org.jooq.test._.TestStatisticsListener;
|
||||
@ -874,12 +876,26 @@ public abstract class jOOQAbstractTest<
|
||||
.withDefaultSchema(defaultSchema));
|
||||
|
||||
DSLContext create = create(settings);
|
||||
create.configuration().getExecuteListeners().add(new TestStatisticsListener());
|
||||
create.configuration().getExecuteListeners().add(new PrettyPrinter());
|
||||
create.configuration().getExecuteListeners().add(new LifecycleWatcherListener());
|
||||
addListeners(create.configuration(),
|
||||
new TestStatisticsListener(),
|
||||
new PrettyPrinter(),
|
||||
new LifecycleWatcherListener());
|
||||
|
||||
return create;
|
||||
}
|
||||
|
||||
protected final List<ExecuteListener> getListeners(org.jooq.Configuration configuration) {
|
||||
|
||||
// Most test cases run with the DefaultExecuteListenerProvider,
|
||||
// which (inofficially) exposes a mutable List
|
||||
DefaultExecuteListenerProvider provider = (DefaultExecuteListenerProvider) configuration.getExecuteListenerProvider();
|
||||
return provider.provide();
|
||||
}
|
||||
|
||||
protected final void addListeners(org.jooq.Configuration configuration, ExecuteListener... listeners) {
|
||||
getListeners(configuration).addAll(Arrays.asList(listeners));
|
||||
}
|
||||
|
||||
protected final SQLDialect getDialect() {
|
||||
return create().configuration().getDialect();
|
||||
}
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
package org.jooq;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jooq.conf.Settings;
|
||||
@ -147,10 +146,12 @@ public interface Configuration extends Serializable {
|
||||
Object setData(Object key, Object value);
|
||||
|
||||
/**
|
||||
* Get the configured <code>ExecuteListeners</code> from this configuration.
|
||||
* Get the configured <code>ExecuteListenerProvider</code> from this
|
||||
* configuration.
|
||||
* <p>
|
||||
* This method allows for retrieving the configured
|
||||
* <code>ExecuteListener</code> instances from this configuration. These
|
||||
* <code>ExecuteListenerProvider</code> from this configuration. The
|
||||
* provider will provide jOOQ with {@link ExecuteListener} instances. These
|
||||
* instances receive execution lifecycle notification events every time jOOQ
|
||||
* executes queries. jOOQ makes no assumptions about the internal state of
|
||||
* these listeners, i.e. listener instances may
|
||||
@ -167,9 +168,56 @@ public interface Configuration extends Serializable {
|
||||
* listeners will never be exposed through this method, though.
|
||||
*
|
||||
* @return The configured set of execute listeners.
|
||||
* @see ExecuteListenerProvider
|
||||
* @see ExecuteListener
|
||||
* @see ExecuteContext
|
||||
*/
|
||||
List<ExecuteListener> getExecuteListeners();
|
||||
ExecuteListenerProvider getExecuteListenerProvider();
|
||||
|
||||
/**
|
||||
* Create a derived configuration from this one, without changing any
|
||||
* properties.
|
||||
*
|
||||
* @return The derived configuration.
|
||||
*/
|
||||
Configuration derive();
|
||||
|
||||
/**
|
||||
* Create a derived configuration from this one, with a new dialect.
|
||||
*
|
||||
* @param newDialect The new dialect to be contained in the derived
|
||||
* configuration.
|
||||
* @return The derived configuration.
|
||||
*/
|
||||
Configuration derive(SQLDialect newDialect);
|
||||
|
||||
/**
|
||||
* Create a derived configuration from this one, with a new connection
|
||||
* provider.
|
||||
*
|
||||
* @param newConnectionProvider The new connection provider to be contained
|
||||
* in the derived configuration.
|
||||
* @return The derived configuration.
|
||||
*/
|
||||
Configuration derive(ConnectionProvider newConnectionProvider);
|
||||
|
||||
/**
|
||||
* Create a derived configuration from this one, with new settings.
|
||||
*
|
||||
* @param newSettings The new settings to be contained in the derived
|
||||
* configuration.
|
||||
* @return The derived configuration.
|
||||
*/
|
||||
Configuration derive(Settings newSettings);
|
||||
|
||||
/**
|
||||
* Create a derived configuration from this one, with a new execute listener
|
||||
* provider.
|
||||
*
|
||||
* @param newExecuteListenerProvider The new execute listener provider to be
|
||||
* contained in the derived configuration.
|
||||
* @return The derived configuration.
|
||||
*/
|
||||
Configuration derive(ExecuteListenerProvider newExecuteListenerProvider);
|
||||
|
||||
}
|
||||
|
||||
65
jOOQ/src/main/java/org/jooq/ExecuteListenerProvider.java
Normal file
65
jOOQ/src/main/java/org/jooq/ExecuteListenerProvider.java
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2013, 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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A provider for {@link ExecuteListener} instances.
|
||||
* <p>
|
||||
* In order to facilitate the lifecycle management of
|
||||
* <code>ExecuteListener</code> instances that are provided to a jOOQ
|
||||
* {@link Configuration}, clients can implement this API. To jOOQ, it is thus
|
||||
* irrelevant, if execute listeners are stateful or stateless, local to an
|
||||
* execution, or global to an application.
|
||||
*
|
||||
* @author Lukas Eder
|
||||
* @see ExecuteListener
|
||||
* @see Configuration
|
||||
*/
|
||||
public interface ExecuteListenerProvider {
|
||||
|
||||
/**
|
||||
* Provide a list of <code>ExecuteListener</code> instances.
|
||||
* <p>
|
||||
* jOOQ will issue {@link ExecuteListener} notification events to each
|
||||
* listener in the order of iteration of the returned list.
|
||||
*
|
||||
* @return A list of <code>ExecuteListener</code> instances.
|
||||
* @see ExecuteListener
|
||||
*/
|
||||
List<ExecuteListener> provide();
|
||||
}
|
||||
@ -49,6 +49,7 @@ import org.jooq.BatchBindStep;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.Query;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
@ -95,55 +96,45 @@ class BatchCRUD implements Batch {
|
||||
|
||||
private final int[] executePrepared() {
|
||||
Map<String, List<Query>> queries = new LinkedHashMap<String, List<Query>>();
|
||||
|
||||
Boolean executeLogging = configuration.getSettings().isExecuteLogging();
|
||||
QueryCollector collector = new QueryCollector();
|
||||
|
||||
try {
|
||||
// [#1537] Communicate with UpdatableRecordImpl
|
||||
configuration.setData(Utils.DATA_OMIT_RETURNING_CLAUSE, true);
|
||||
// Add the QueryCollector to intercept query execution after rendering
|
||||
List<ExecuteListener> listeners = new ArrayList<ExecuteListener>(configuration.getExecuteListenerProvider().provide());
|
||||
listeners.add(collector);
|
||||
Configuration local = configuration.derive(new DefaultExecuteListenerProvider(listeners));
|
||||
|
||||
// Add the QueryCollector to intercept query execution after rendering
|
||||
configuration.getExecuteListeners().add(collector);
|
||||
// [#1537] Communicate with UpdatableRecordImpl
|
||||
local.setData(Utils.DATA_OMIT_RETURNING_CLAUSE, true);
|
||||
|
||||
// [#1529] Avoid DEBUG logging of single INSERT / UPDATE statements
|
||||
configuration.getSettings().setExecuteLogging(false);
|
||||
// [#1529] Avoid DEBUG logging of single INSERT / UPDATE statements
|
||||
local.getSettings().setExecuteLogging(false);
|
||||
|
||||
for (int i = 0; i < records.length; i++) {
|
||||
Configuration previous = ((AttachableInternal) records[i]).getConfiguration();
|
||||
for (int i = 0; i < records.length; i++) {
|
||||
Configuration previous = ((AttachableInternal) records[i]).getConfiguration();
|
||||
|
||||
try {
|
||||
records[i].attach(configuration);
|
||||
executeAction(i);
|
||||
}
|
||||
catch (QueryCollectorException e) {
|
||||
Query query = e.getQuery();
|
||||
String sql = e.getSQL();
|
||||
try {
|
||||
records[i].attach(local);
|
||||
executeAction(i);
|
||||
}
|
||||
catch (QueryCollectorException e) {
|
||||
Query query = e.getQuery();
|
||||
String sql = e.getSQL();
|
||||
|
||||
// Aggregate executable queries by identical SQL
|
||||
if (query.isExecutable()) {
|
||||
List<Query> list = queries.get(sql);
|
||||
// Aggregate executable queries by identical SQL
|
||||
if (query.isExecutable()) {
|
||||
List<Query> list = queries.get(sql);
|
||||
|
||||
if (list == null) {
|
||||
list = new ArrayList<Query>();
|
||||
queries.put(sql, list);
|
||||
}
|
||||
|
||||
list.add(query);
|
||||
if (list == null) {
|
||||
list = new ArrayList<Query>();
|
||||
queries.put(sql, list);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
records[i].attach(previous);
|
||||
|
||||
list.add(query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the original factory
|
||||
finally {
|
||||
configuration.getData().remove(Utils.DATA_OMIT_RETURNING_CLAUSE);
|
||||
|
||||
configuration.getExecuteListeners().remove(collector);
|
||||
configuration.getSettings().setExecuteLogging(executeLogging);
|
||||
finally {
|
||||
records[i].attach(previous);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute one batch statement for each identical SQL statement. Every
|
||||
@ -176,32 +167,27 @@ class BatchCRUD implements Batch {
|
||||
List<Query> queries = new ArrayList<Query>();
|
||||
QueryCollector collector = new QueryCollector();
|
||||
|
||||
try {
|
||||
configuration.getExecuteListeners().add(collector);
|
||||
List<ExecuteListener> listeners = new ArrayList<ExecuteListener>(configuration.getExecuteListenerProvider().provide());
|
||||
listeners.add(collector);
|
||||
Configuration local = configuration.derive(new DefaultExecuteListenerProvider(listeners));
|
||||
|
||||
for (int i = 0; i < records.length; i++) {
|
||||
Configuration previous = ((AttachableInternal) records[i]).getConfiguration();
|
||||
for (int i = 0; i < records.length; i++) {
|
||||
Configuration previous = ((AttachableInternal) records[i]).getConfiguration();
|
||||
|
||||
try {
|
||||
records[i].attach(configuration);
|
||||
executeAction(i);
|
||||
}
|
||||
catch (QueryCollectorException e) {
|
||||
Query query = e.getQuery();
|
||||
try {
|
||||
records[i].attach(local);
|
||||
executeAction(i);
|
||||
}
|
||||
catch (QueryCollectorException e) {
|
||||
Query query = e.getQuery();
|
||||
|
||||
if (query.isExecutable()) {
|
||||
queries.add(query);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
records[i].attach(previous);
|
||||
if (query.isExecutable()) {
|
||||
queries.add(query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the original factory
|
||||
finally {
|
||||
configuration.getExecuteListeners().remove(collector);
|
||||
finally {
|
||||
records[i].attach(previous);
|
||||
}
|
||||
}
|
||||
|
||||
// Resulting statements can be batch executed in their requested order
|
||||
|
||||
@ -82,8 +82,8 @@ import org.jooq.BindContext;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.ConnectionProvider;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.Cursor;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.DeleteQuery;
|
||||
import org.jooq.DeleteWhereStep;
|
||||
@ -215,7 +215,7 @@ class DSLContextImpl implements DSLContext, Serializable {
|
||||
}
|
||||
|
||||
DSLContextImpl(SQLDialect dialect, Settings settings) {
|
||||
this(new DefaultConfiguration(new NoConnectionProvider(), dialect, settings, null));
|
||||
this(new DefaultConfiguration(new NoConnectionProvider(), null, dialect, settings, null));
|
||||
}
|
||||
|
||||
DSLContextImpl(Connection connection, SQLDialect dialect) {
|
||||
@ -223,7 +223,7 @@ class DSLContextImpl implements DSLContext, Serializable {
|
||||
}
|
||||
|
||||
DSLContextImpl(Connection connection, SQLDialect dialect, Settings settings) {
|
||||
this(new DefaultConfiguration(new DefaultConnectionProvider(connection), dialect, settings, null));
|
||||
this(new DefaultConfiguration(new DefaultConnectionProvider(connection), null, dialect, settings, null));
|
||||
}
|
||||
|
||||
DSLContextImpl(DataSource datasource, SQLDialect dialect) {
|
||||
@ -231,7 +231,7 @@ class DSLContextImpl implements DSLContext, Serializable {
|
||||
}
|
||||
|
||||
DSLContextImpl(DataSource datasource, SQLDialect dialect, Settings settings) {
|
||||
this(new DefaultConfiguration(new DataSourceConnectionProvider(datasource), dialect, settings, null));
|
||||
this(new DefaultConfiguration(new DataSourceConnectionProvider(datasource), null, dialect, settings, null));
|
||||
}
|
||||
|
||||
DSLContextImpl(ConnectionProvider connectionProvider, SQLDialect dialect) {
|
||||
@ -239,7 +239,7 @@ class DSLContextImpl implements DSLContext, Serializable {
|
||||
}
|
||||
|
||||
DSLContextImpl(ConnectionProvider connectionProvider, SQLDialect dialect, Settings settings) {
|
||||
this(new DefaultConfiguration(connectionProvider, dialect, settings, null));
|
||||
this(new DefaultConfiguration(connectionProvider, null, dialect, settings, null));
|
||||
}
|
||||
|
||||
DSLContextImpl(Configuration configuration) {
|
||||
|
||||
@ -37,9 +37,11 @@ package org.jooq.impl;
|
||||
|
||||
import static org.jooq.SQLDialect.SQL99;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@ -48,7 +50,7 @@ import javax.xml.bind.JAXB;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.ConnectionProvider;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.ExecuteListenerProvider;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.conf.SettingsTools;
|
||||
@ -61,6 +63,7 @@ import org.jooq.conf.SettingsTools;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class DefaultConfiguration implements Configuration {
|
||||
|
||||
/**
|
||||
@ -68,39 +71,136 @@ public class DefaultConfiguration implements Configuration {
|
||||
*/
|
||||
private static final long serialVersionUID = 8193158984283234708L;
|
||||
|
||||
private final ConnectionProvider connectionProvider;
|
||||
// Configuration objects
|
||||
private final SQLDialect dialect;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private final org.jooq.SchemaMapping mapping;
|
||||
private final Settings settings;
|
||||
private final ConcurrentHashMap<Object, Object> data;
|
||||
private final List<ExecuteListener> listeners;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
// Non-serializable Configuration objects
|
||||
private transient ConnectionProvider connectionProvider;
|
||||
private transient ExecuteListenerProvider listenerProvider;
|
||||
|
||||
// Derived objects
|
||||
private final org.jooq.SchemaMapping mapping;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XXX: Constructors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a new "empty" configuration object.
|
||||
* <p>
|
||||
* This can be used as is, as a "dummy" configuration object, or as a base
|
||||
* implementation for creating more sophisticated "derived" configurations
|
||||
* through the various <code>derive()</code> methods.
|
||||
*/
|
||||
public DefaultConfiguration() {
|
||||
this(new NoConnectionProvider(), SQL99, SettingsTools.defaultSettings(), null);
|
||||
this(
|
||||
new NoConnectionProvider(),
|
||||
new DefaultExecuteListenerProvider(),
|
||||
SQL99,
|
||||
SettingsTools.defaultSettings(),
|
||||
null);
|
||||
}
|
||||
|
||||
public DefaultConfiguration(Configuration configuration) {
|
||||
/**
|
||||
* Create a new "derived" configuration object from a pre-existing one.
|
||||
* <p>
|
||||
* This copies all properties from a pre-existing configuration into a new,
|
||||
* derived one.
|
||||
*
|
||||
* @param configuration The pre-existing configuration.
|
||||
*/
|
||||
DefaultConfiguration(Configuration configuration) {
|
||||
this(
|
||||
configuration.getConnectionProvider(),
|
||||
configuration.getExecuteListenerProvider(),
|
||||
configuration.getDialect(),
|
||||
configuration.getSettings(),
|
||||
configuration.getData()
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public DefaultConfiguration(ConnectionProvider connectionProvider, SQLDialect dialect, Settings settings, Map<Object, Object> data) {
|
||||
/**
|
||||
* Create the actual configuration object.
|
||||
* <p>
|
||||
* This constructor has been made package-private to allow for adding new
|
||||
* configuration properties in the future, without breaking client code.
|
||||
* Consider creating a configuration by chaining calls to various
|
||||
* <code>derive()</code> methods.
|
||||
*/
|
||||
DefaultConfiguration(
|
||||
ConnectionProvider connectionProvider,
|
||||
ExecuteListenerProvider listenerProvider,
|
||||
SQLDialect dialect,
|
||||
Settings settings,
|
||||
Map<Object, Object> data)
|
||||
{
|
||||
this.connectionProvider = connectionProvider;
|
||||
this.listenerProvider = listenerProvider != null
|
||||
? listenerProvider
|
||||
: new DefaultExecuteListenerProvider();
|
||||
|
||||
this.dialect = dialect;
|
||||
this.settings = settings != null ? settings : SettingsTools.defaultSettings();
|
||||
this.settings = settings != null
|
||||
? SettingsTools.clone(settings)
|
||||
: SettingsTools.defaultSettings();
|
||||
|
||||
this.data = data != null
|
||||
? new ConcurrentHashMap<Object, Object>(data)
|
||||
: new ConcurrentHashMap<Object, Object>();
|
||||
|
||||
this.mapping = new org.jooq.SchemaMapping(this);
|
||||
this.data = data != null ? new ConcurrentHashMap<Object, Object>(data) : new ConcurrentHashMap<Object, Object>();
|
||||
this.listeners = new ArrayList<ExecuteListener>();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XXX: Deriving configurations
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final Configuration derive() {
|
||||
return new DefaultConfiguration(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final Configuration derive(SQLDialect newDialect) {
|
||||
return new DefaultConfiguration(connectionProvider, listenerProvider, newDialect, settings, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final Configuration derive(ConnectionProvider newConnectionProvider) {
|
||||
return new DefaultConfiguration(newConnectionProvider, listenerProvider, dialect, settings, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final Configuration derive(Settings newSettings) {
|
||||
return new DefaultConfiguration(connectionProvider, listenerProvider, dialect, newSettings, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final Configuration derive(ExecuteListenerProvider newExecuteListenerProvider) {
|
||||
return new DefaultConfiguration(connectionProvider, newExecuteListenerProvider, dialect, settings, data);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XXX: Getters
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -162,19 +262,8 @@ public class DefaultConfiguration implements Configuration {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final List<ExecuteListener> getExecuteListeners() {
|
||||
return listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the execute listeners onto this configuration.
|
||||
*/
|
||||
public final void setExecuteListeners(List<ExecuteListener> listeners) {
|
||||
this.listeners.clear();
|
||||
|
||||
if (listeners != null) {
|
||||
listeners.addAll(listeners);
|
||||
}
|
||||
public final ExecuteListenerProvider getExecuteListenerProvider() {
|
||||
return listenerProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -186,5 +275,29 @@ public class DefaultConfiguration implements Configuration {
|
||||
",\n\tdialect=" + dialect +
|
||||
",\n\tdata=" + data +
|
||||
",\n\tsettings=\n\t\t" + writer.toString().trim().replace("\n", "\n\t\t") +
|
||||
"\n]"; }
|
||||
"\n]";
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XXX: Serialisation
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
oos.defaultWriteObject();
|
||||
|
||||
// Allow these objects to be non-serializable
|
||||
oos.writeObject(connectionProvider instanceof Serializable
|
||||
? connectionProvider
|
||||
: null);
|
||||
oos.writeObject(listenerProvider instanceof Serializable
|
||||
? listenerProvider
|
||||
: null);
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
ois.defaultReadObject();
|
||||
|
||||
connectionProvider = (ConnectionProvider) ois.readObject();
|
||||
listenerProvider = (ExecuteListenerProvider) ois.readObject();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2013, 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.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.ExecuteListenerProvider;
|
||||
|
||||
/**
|
||||
* A default implementation for {@link ExecuteListenerProvider}.
|
||||
* <p>
|
||||
* This implementation just wraps a <code>List</code> of {@link ExecuteListener}
|
||||
* instances, always providing the same.
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class DefaultExecuteListenerProvider implements ExecuteListenerProvider, Serializable {
|
||||
|
||||
/**
|
||||
* Generated UID.
|
||||
*/
|
||||
private static final long serialVersionUID = -2122007794302549679L;
|
||||
|
||||
/**
|
||||
* The delegate list.
|
||||
*/
|
||||
private List<ExecuteListener> listeners;
|
||||
|
||||
/**
|
||||
* Create a new provider instance with an empty <code>ArrayList</code>
|
||||
* argument.
|
||||
*/
|
||||
public DefaultExecuteListenerProvider() {
|
||||
this(new ArrayList<ExecuteListener>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new provider instance from an argument <code>List</code>.
|
||||
*
|
||||
* @param listeners The argument list.
|
||||
*/
|
||||
public DefaultExecuteListenerProvider(List<ExecuteListener> listeners) {
|
||||
this.listeners = listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final List<ExecuteListener> provide() {
|
||||
return listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "" + listeners;
|
||||
}
|
||||
}
|
||||
@ -38,11 +38,11 @@ package org.jooq.impl;
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static org.jooq.SQLDialect.CUBRID;
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
import static org.jooq.impl.DefaultExecuteContext.localConnection;
|
||||
import static org.jooq.impl.DSL.escape;
|
||||
import static org.jooq.impl.DSL.getDataType;
|
||||
import static org.jooq.impl.DSL.nullSafe;
|
||||
import static org.jooq.impl.DSL.val;
|
||||
import static org.jooq.impl.DefaultExecuteContext.localConnection;
|
||||
import static org.jooq.tools.jdbc.JDBCUtils.safeFree;
|
||||
import static org.jooq.tools.jdbc.JDBCUtils.wasNull;
|
||||
import static org.jooq.tools.reflect.Reflect.accessible;
|
||||
@ -86,13 +86,14 @@ import org.jooq.Attachable;
|
||||
import org.jooq.AttachableInternal;
|
||||
import org.jooq.BindContext;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.Converter;
|
||||
import org.jooq.Cursor;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.EnumType;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.ExecuteListenerProvider;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Param;
|
||||
import org.jooq.QueryPart;
|
||||
@ -1095,13 +1096,16 @@ final class Utils {
|
||||
*/
|
||||
static final List<ExecuteListener> getListeners(ExecuteContext ctx) {
|
||||
List<ExecuteListener> result = new ArrayList<ExecuteListener>();
|
||||
|
||||
if (!FALSE.equals(ctx.configuration().getSettings().isExecuteLogging())) {
|
||||
result.add(new StopWatchListener());
|
||||
result.add(new LoggerListener());
|
||||
}
|
||||
|
||||
result.addAll(ctx.configuration().getExecuteListeners());
|
||||
ExecuteListenerProvider provider = ctx.configuration().getExecuteListenerProvider();
|
||||
if (provider != null) {
|
||||
result.addAll(provider.provide());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user