You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2026/05/31 18:51:28 UTC
(cayenne) 02/04: Translators as stateless services producing immutable TranslatedXyz records
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 2f8d434f5fea8aea606ef44d2cf765f70ce368d2
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 13:12:29 2026 -0400
Translators as stateless services producing immutable TranslatedXyz records
* batch translators
---
.../org/apache/cayenne/crypto/CryptoModule.java | 9 +-
.../crypto/batch/CryptoBatchTranslator.java | 66 ++++++++++
.../CryptoBatchTranslatorFactoryDecorator.java | 88 -------------
.../dbsync/reverse/configuration/ToolsModule.java | 10 +-
.../java/org/apache/cayenne/access/DataNode.java | 61 ++++-----
.../apache/cayenne/access/jdbc/BaseSQLAction.java | 2 +-
.../apache/cayenne/access/jdbc/BatchAction.java | 36 +++---
.../cayenne/access/jdbc/SQLTemplateAction.java | 3 +-
.../apache/cayenne/access/jdbc/SelectAction.java | 5 +-
.../translator/batch/BaseBatchTranslator.java | 54 ++++----
...hTranslatorFactory.java => BatchRowBinder.java} | 22 ++--
.../access/translator/batch/BatchTranslator.java | 44 ++++---
.../batch/DefaultBatchTranslatorFactory.java | 57 ---------
.../translator/batch/DeleteBatchTranslator.java | 33 ++---
.../translator/batch/InsertBatchTranslator.java | 22 ++--
.../batch/SoftDeleteBatchTranslator.java | 54 ++++++--
.../batch/SoftDeleteTranslatorFactory.java | 69 ----------
.../translator/batch/TranslatedBatch.java} | 27 ++--
.../translator/batch/UpdateBatchTranslator.java | 18 +--
.../batch/legacy/DefaultBatchTranslator.java | 112 ----------------
.../cayenne/configuration/runtime/CoreModule.java | 10 +-
.../runtime/DefaultDataNodeFactory.java | 21 ++-
.../cayenne/dba/oracle/OracleActionBuilder.java | 13 --
.../cayenne/access/jdbc/BatchActionLockingIT.java | 9 +-
.../translator/batch/DeleteBatchTranslatorIT.java | 24 +---
.../translator/batch/InsertBatchTranslatorIT.java | 19 +--
.../batch/SoftDeleteBatchTranslatorIT.java | 23 ++--
.../translator/batch/UpdateBatchTranslatorIT.java | 23 +---
.../batch/legacy/DefaultBatchTranslatorIT.java | 141 ---------------------
.../runtime/DataDomainProviderTest.java | 10 +-
.../runtime/DefaultDbAdapterFactoryTest.java | 18 ++-
31 files changed, 362 insertions(+), 741 deletions(-)
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java
index 9f619393e..d8beb738a 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java
@@ -19,9 +19,10 @@
package org.apache.cayenne.crypto;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.configuration.DataMapLoader;
-import org.apache.cayenne.crypto.batch.CryptoBatchTranslatorFactoryDecorator;
+import org.apache.cayenne.crypto.batch.CryptoBatchTranslator;
+import org.apache.cayenne.di.Key;
import org.apache.cayenne.crypto.cipher.DefaultCipherFactory;
import org.apache.cayenne.crypto.key.JceksKeySource;
import org.apache.cayenne.crypto.map.CryptoDataMapLoader;
@@ -152,7 +153,9 @@ public class CryptoModule implements Module {
binder.bind(TransformerFactory.class).to(DefaultTransformerFactory.class);
binder.decorate(DataMapLoader.class).before(CryptoDataMapLoader.class);
- binder.decorate(BatchTranslatorFactory.class).before(CryptoBatchTranslatorFactoryDecorator.class);
+ binder.decorate(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).before(CryptoBatchTranslator.class);
+ binder.decorate(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).before(CryptoBatchTranslator.class);
+ binder.decorate(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).before(CryptoBatchTranslator.class);
binder.bind(RowReaderFactory.class).to(CryptoRowReaderFactoryDecorator.class);
// decorate Crypto's own services to allow Cayenne to operate over plaintext entities even if crypto keys are
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslator.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslator.java
new file mode 100644
index 000000000..c27423bcd
--- /dev/null
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslator.java
@@ -0,0 +1,66 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.crypto.batch;
+
+import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.batch.TranslatedBatch;
+import org.apache.cayenne.crypto.transformer.BindingsTransformer;
+import org.apache.cayenne.crypto.transformer.TransformerFactory;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.query.BatchQueryRow;
+
+/**
+ * @since 5.0
+ */
+public class CryptoBatchTranslator<T extends BatchQuery> implements BatchTranslator<T> {
+
+ private final TransformerFactory transformerFactory;
+ private final BatchTranslator<T> delegate;
+
+ public CryptoBatchTranslator(
+ @Inject BatchTranslator<T> delegate,
+ @Inject TransformerFactory transformerFactory) {
+
+ this.transformerFactory = transformerFactory;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public TranslatedBatch translate(T query, DbAdapter adapter) {
+ TranslatedBatch translated = delegate.translate(query, adapter);
+ BindingsTransformer encryptor = transformerFactory.encryptor(translated.bindings(), adapter.getExtendedTypes());
+
+ return encryptor != null
+ ? new TranslatedBatch(translated.sql(), translated.bindings(), (bindings, row) -> transform(bindings, row, translated, encryptor))
+ : translated;
+ }
+
+ private static ParameterBinding[] transform(
+ ParameterBinding[] bindings,
+ BatchQueryRow row,
+ TranslatedBatch translated,
+ BindingsTransformer encryptor) {
+ ParameterBinding[] updated = translated.binder().bind(bindings, row);
+ encryptor.transform(updated);
+ return updated;
+ }
+}
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java
deleted file mode 100644
index ddc021d6c..000000000
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-package org.apache.cayenne.crypto.batch;
-
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.batch.BatchTranslator;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
-import org.apache.cayenne.crypto.transformer.BindingsTransformer;
-import org.apache.cayenne.crypto.transformer.TransformerFactory;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.BatchQueryRow;
-
-/**
- * @since 4.0
- */
-public class CryptoBatchTranslatorFactoryDecorator implements BatchTranslatorFactory {
-
- private TransformerFactory cryptoFactory;
- private BatchTranslatorFactory delegate;
-
- public CryptoBatchTranslatorFactoryDecorator(@Inject BatchTranslatorFactory delegate,
- @Inject TransformerFactory cryptoFactory) {
-
- this.cryptoFactory = cryptoFactory;
- this.delegate = delegate;
- }
-
- @Override
- public BatchTranslator translator(BatchQuery query, final DbAdapter adapter, String trimFunction) {
- final BatchTranslator delegateTranslator = delegate.translator(query, adapter, trimFunction);
-
- return new BatchTranslator() {
-
- private boolean encryptorCompiled;
- private BindingsTransformer encryptor;
-
- private void ensureEncryptorCompiled() {
- if (!encryptorCompiled) {
- encryptor = cryptoFactory.encryptor(getBindings(), adapter.getExtendedTypes());
- encryptorCompiled = true;
- }
- }
-
- @Override
- public String getSql() {
- return delegateTranslator.getSql();
- }
-
- @Override
- public ParameterBinding[] getBindings() {
- return delegateTranslator.getBindings();
- }
-
- @Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
-
- ensureEncryptorCompiled();
-
- ParameterBinding[] bindings = delegateTranslator.updateBindings(row);
-
- if (encryptor != null) {
- encryptor.transform(bindings);
- }
-
- return bindings;
- }
- };
- }
-
-}
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index 033d39187..1515f5c14 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -23,8 +23,10 @@ import org.apache.cayenne.access.flush.DataDomainFlushActionFactory;
import org.apache.cayenne.access.flush.DefaultDataDomainFlushActionFactory;
import org.apache.cayenne.access.flush.operation.DbRowOpSorter;
import org.apache.cayenne.access.flush.operation.DefaultDbRowOpSorter;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
-import org.apache.cayenne.access.translator.batch.DefaultBatchTranslatorFactory;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator;
+import org.apache.cayenne.access.translator.batch.InsertBatchTranslator;
+import org.apache.cayenne.access.translator.batch.UpdateBatchTranslator;
import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
@@ -153,7 +155,9 @@ public class ToolsModule implements Module {
binder.bind(Key.get(ResourceLocator.class, Constants.RESOURCE_LOCATOR)).to(ClassLoaderResourceLocator.class);
binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- binder.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).to(InsertBatchTranslator.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).to(UpdateBatchTranslator.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).to(DeleteBatchTranslator.class);
binder.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
index 5ba5b83b3..739140ed5 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
@@ -21,24 +21,20 @@ package org.apache.cayenne.access;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
-import org.apache.cayenne.access.jdbc.RowDescriptor;
-import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
-import org.apache.cayenne.access.jdbc.reader.RowReader;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
import org.apache.cayenne.access.translator.batch.BatchTranslator;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
import org.apache.cayenne.access.translator.select.SelectTranslator;
-import org.apache.cayenne.access.translator.select.TranslatedSelect;
+import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.JdbcAdapter;
import org.apache.cayenne.log.JdbcEventLogger;
import org.apache.cayenne.log.NoopJdbcEventLogger;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.query.DeleteBatchQuery;
+import org.apache.cayenne.query.InsertBatchQuery;
import org.apache.cayenne.query.Query;
-import org.apache.cayenne.query.QueryMetadata;
-import org.apache.cayenne.query.Select;
+import org.apache.cayenne.query.UpdateBatchQuery;
import org.apache.cayenne.tx.BaseTransaction;
import org.apache.cayenne.tx.Transaction;
import org.apache.cayenne.util.ToStringBuilder;
@@ -70,7 +66,9 @@ public class DataNode {
private JdbcEventLogger jdbcEventLogger;
private RowReaderFactory rowReaderFactory;
- private BatchTranslatorFactory batchTranslatorFactory;
+ private BatchTranslator<InsertBatchQuery> insertBatchTranslator;
+ private BatchTranslator<UpdateBatchQuery> updateBatchTranslator;
+ private BatchTranslator<DeleteBatchQuery> deleteBatchTranslator;
private SelectTranslator selectTranslator;
private SQLTemplateTranslator sqlTemplateTranslator;
@@ -316,54 +314,59 @@ public class DataNode {
/**
- * Creates a {@link RowReader} using internal {@link RowReaderFactory}.
- *
* @since 4.0
*/
- public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) {
- return rowReaderFactory.rowReader(descriptor, queryMetadata, getAdapter());
+ public RowReaderFactory getRowReaderFactory() {
+ return rowReaderFactory;
}
/**
* @since 4.0
*/
- public BatchTranslator batchTranslator(BatchQuery query, String trimFunction) {
- return batchTranslatorFactory.translator(query, getAdapter(), trimFunction);
+ public void setRowReaderFactory(RowReaderFactory rowReaderFactory) {
+ this.rowReaderFactory = rowReaderFactory;
}
/**
* @since 5.0
*/
- public TranslatedSelect translateSelect(Select<?> query) {
- return selectTranslator.translate(query, getAdapter(), getEntityResolver());
+ public BatchTranslator<InsertBatchQuery> getInsertBatchTranslator() {
+ return insertBatchTranslator;
}
/**
- * @since 4.0
+ * @since 5.0
*/
- public RowReaderFactory getRowReaderFactory() {
- return rowReaderFactory;
+ public void setInsertBatchTranslator(BatchTranslator<InsertBatchQuery> insertBatchTranslator) {
+ this.insertBatchTranslator = insertBatchTranslator;
}
/**
- * @since 4.0
+ * @since 5.0
*/
- public void setRowReaderFactory(RowReaderFactory rowReaderFactory) {
- this.rowReaderFactory = rowReaderFactory;
+ public BatchTranslator<UpdateBatchQuery> getUpdateBatchTranslator() {
+ return updateBatchTranslator;
}
/**
- * @since 4.0
+ * @since 5.0
*/
- public BatchTranslatorFactory getBatchTranslatorFactory() {
- return batchTranslatorFactory;
+ public void setUpdateBatchTranslator(BatchTranslator<UpdateBatchQuery> updateBatchTranslator) {
+ this.updateBatchTranslator = updateBatchTranslator;
}
/**
- * @since 4.0
+ * @since 5.0
+ */
+ public BatchTranslator<DeleteBatchQuery> getDeleteBatchTranslator() {
+ return deleteBatchTranslator;
+ }
+
+ /**
+ * @since 5.0
*/
- public void setBatchTranslatorFactory(BatchTranslatorFactory batchTranslatorFactory) {
- this.batchTranslatorFactory = batchTranslatorFactory;
+ public void setDeleteBatchTranslator(BatchTranslator<DeleteBatchQuery> deleteBatchTranslator) {
+ this.deleteBatchTranslator = deleteBatchTranslator;
}
/**
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
index d81eb258e..1a63b8610 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
@@ -56,7 +56,7 @@ public abstract class BaseSQLAction implements SQLAction {
QueryMetadata metadata = query.getMetaData(dataNode.getEntityResolver());
- RowReader<?> rowReader = dataNode.rowReader(descriptor, metadata);
+ RowReader<?> rowReader = dataNode.getRowReaderFactory().rowReader(descriptor, metadata, dataNode.getAdapter());
JDBCResultIterator resultReader = new JDBCResultIterator(null, resultSet, rowReader);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
index 203f07693..ada634f2a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
@@ -19,6 +19,7 @@
package org.apache.cayenne.access.jdbc;
+import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.ObjectId;
import org.apache.cayenne.ResultIterator;
import org.apache.cayenne.access.DataNode;
@@ -26,7 +27,7 @@ import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.OptimisticLockException;
import org.apache.cayenne.access.jdbc.reader.RowReader;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.batch.TranslatedBatch;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.log.JdbcEventLogger;
import org.apache.cayenne.map.DbAttribute;
@@ -34,7 +35,9 @@ import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.query.BatchQuery;
import org.apache.cayenne.query.BatchQueryRow;
+import org.apache.cayenne.query.DeleteBatchQuery;
import org.apache.cayenne.query.InsertBatchQuery;
+import org.apache.cayenne.query.UpdateBatchQuery;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -73,15 +76,21 @@ public class BatchAction extends BaseSQLAction {
@Override
public void performAction(Connection connection, OperationObserver observer) throws Exception {
- BatchTranslator translator = createTranslator();
+ DbAdapter adapter = dataNode.getAdapter();
+ TranslatedBatch translated = switch (query) {
+ case InsertBatchQuery insert -> dataNode.getInsertBatchTranslator().translate(insert, adapter);
+ case UpdateBatchQuery update -> dataNode.getUpdateBatchTranslator().translate(update, adapter);
+ case DeleteBatchQuery delete -> dataNode.getDeleteBatchTranslator().translate(delete, adapter);
+ case null, default -> throw new CayenneRuntimeException("Unsupported batch query: %s", query);
+ };
boolean isBatch = canRunAsBatch();
boolean generatesKeys = hasGeneratedKeys() && supportsGeneratedKeys(isBatch);
if (isBatch) {
- runAsBatch(connection, translator, observer, generatesKeys);
+ runAsBatch(connection, translated, observer, generatesKeys);
} else {
- runAsIndividualQueries(connection, translator, observer, generatesKeys);
+ runAsIndividualQueries(connection, translated, observer, generatesKeys);
}
}
@@ -99,14 +108,10 @@ public class BatchAction extends BaseSQLAction {
return true;
}
- protected BatchTranslator createTranslator() {
- return dataNode.batchTranslator(query, null);
- }
-
- protected void runAsBatch(Connection con, BatchTranslator translator, OperationObserver delegate, boolean generatesKeys)
+ protected void runAsBatch(Connection con, TranslatedBatch translated, OperationObserver delegate, boolean generatesKeys)
throws Exception {
- String sql = translator.getSql();
+ String sql = translated.sql();
JdbcEventLogger logger = dataNode.getJdbcEventLogger();
boolean isLoggable = logger.isLoggable();
@@ -120,7 +125,7 @@ public class BatchAction extends BaseSQLAction {
try (PreparedStatement statement = prepareStatement(con, sql, adapter, generatesKeys)) {
for (BatchQueryRow row : query.getRows()) {
- ParameterBinding[] bindings = translator.updateBindings(row);
+ ParameterBinding[] bindings = translated.updateBindings(row);
logger.logQueryParameters("batch bind", bindings);
for (ParameterBinding b : bindings) {
adapter.bindParameter(statement, b);
@@ -159,7 +164,7 @@ public class BatchAction extends BaseSQLAction {
/**
* Executes batch as individual queries over the same prepared statement.
*/
- protected void runAsIndividualQueries(Connection connection, BatchTranslator translator,
+ protected void runAsIndividualQueries(Connection connection, TranslatedBatch translated,
OperationObserver delegate, boolean generatesKeys) throws Exception {
if(query.getRows().isEmpty()) {
@@ -169,7 +174,7 @@ public class BatchAction extends BaseSQLAction {
JdbcEventLogger logger = dataNode.getJdbcEventLogger();
boolean useOptimisticLock = query.isUsingOptimisticLocking();
- String queryStr = translator.getSql();
+ String queryStr = translated.sql();
// log batch SQL execution
logger.log(queryStr);
@@ -181,7 +186,7 @@ public class BatchAction extends BaseSQLAction {
try (PreparedStatement statement = prepareStatement(connection, queryStr, adapter, generatesKeys)) {
for (BatchQueryRow row : query.getRows()) {
- ParameterBinding[] bindings = translator.updateBindings(row);
+ ParameterBinding[] bindings = translated.updateBindings(row);
logger.logQueryParameters("bind", bindings);
for (ParameterBinding b : bindings) {
@@ -283,7 +288,8 @@ public class BatchAction extends BaseSQLAction {
this.keyRowDescriptor = builder.getDescriptor(dataNode.getAdapter().getExtendedTypes());
}
- RowReader<?> rowReader = dataNode.rowReader(keyRowDescriptor, query.getMetaData(dataNode.getEntityResolver()));
+ RowReader<?> rowReader = dataNode.getRowReaderFactory()
+ .rowReader(keyRowDescriptor, query.getMetaData(dataNode.getEntityResolver()), dataNode.getAdapter());
ResultIterator iterator = new JDBCResultIterator(null, keysRS, rowReader);
List<ObjectId> objectIds = new ArrayList<>(rows.size());
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
index c4bd62c6d..5f8a22974 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
@@ -239,7 +239,8 @@ public class SQLTemplateAction implements SQLAction {
ExtendedTypeMap types = dataNode.getAdapter().getExtendedTypes();
RowDescriptorBuilder builder = configureRowDescriptorBuilder(compiled, resultSet);
recreateQueryMetadata(resultSet);
- RowReader<?> rowReader = dataNode.rowReader(builder.getDescriptor(types), queryMetadata);
+ RowReader<?> rowReader = dataNode.getRowReaderFactory()
+ .rowReader(builder.getDescriptor(types), queryMetadata, dataNode.getAdapter());
ResultIterator<?> it = new JDBCResultIterator<>(statement, resultSet, rowReader);
if (iteratedResult) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
index 7553e7aa9..e3e2b5aeb 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
@@ -79,7 +79,8 @@ public class SelectAction extends BaseSQLAction {
long t1 = System.currentTimeMillis();
JdbcEventLogger logger = dataNode.getJdbcEventLogger();
- TranslatedSelect translated = dataNode.translateSelect(query);
+ TranslatedSelect translated = dataNode.getSelectTranslator()
+ .translate(query, dataNode.getAdapter(), dataNode.getEntityResolver());
logger.logQuery(translated.sql(), translated.bindings());
@@ -111,7 +112,7 @@ public class SelectAction extends BaseSQLAction {
.setColumns(translated.resultColumns())
.getDescriptor(dataNode.getAdapter().getExtendedTypes());
- RowReader<?> rowReader = dataNode.rowReader(descriptor, queryMetadata);
+ RowReader<?> rowReader = dataNode.getRowReaderFactory().rowReader(descriptor, queryMetadata, dataNode.getAdapter());
ResultIterator<?> it = new JDBCResultIterator<>(statement, rs, rowReader);
it = forIteratedResult(it, observer, connection, t1, translated.sql());
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java
index d5ab3fa1b..365d3c924 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java
@@ -19,8 +19,6 @@
package org.apache.cayenne.access.translator.batch;
-import java.util.List;
-
import org.apache.cayenne.access.sqlbuilder.ExpressionNodeBuilder;
import org.apache.cayenne.access.sqlbuilder.NodeBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
@@ -31,54 +29,56 @@ import org.apache.cayenne.access.translator.select.DefaultQuotingAppendable;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.query.BatchQueryRow;
+
+import java.util.List;
/**
- * @since 4.2
* @param <T> type of the batch query to translate
+ * @since 4.2
*/
-public abstract class BaseBatchTranslator<T extends BatchQuery> {
+public abstract class BaseBatchTranslator<T extends BatchQuery> implements BatchTranslator<T> {
- protected final BatchTranslatorContext<T> context;
+ @Override
+ public TranslatedBatch translate(T query, DbAdapter adapter) {
+ BatchTranslatorContext<T> context = new BatchTranslatorContext<>(query, adapter);
- protected ParameterBinding[] bindings;
+ String sql = createSql(context);
+ ParameterBinding[] bindings = createBindings(context);
- public BaseBatchTranslator(T query, DbAdapter adapter) {
- this.context = new BatchTranslatorContext<>(query, adapter);
+ return new TranslatedBatch(sql, bindings, (b, row) -> updateBindings(context, b, row));
}
- public ParameterBinding[] getBindings() {
- return bindings;
+ protected abstract String createSql(BatchTranslatorContext<T> context);
+
+ protected ParameterBinding[] createBindings(BatchTranslatorContext<T> context) {
+ return context.getBindings().toArray(new ParameterBinding[0]);
}
- /**
- * This method applies {@link org.apache.cayenne.access.translator.select.BaseSQLTreeProcessor} to the
- * provided SQL tree node and generates SQL string from it.
- *
- * @param nodeBuilder SQL tree node builder
- * @return SQL string
- */
- protected String doTranslate(NodeBuilder nodeBuilder) {
- Node node = nodeBuilder.build();
- // convert to database flavour
- node = context.getAdapter().getSqlTreeProcessor().process(node);
- // generate SQL
+ protected abstract ParameterBinding[] updateBindings(
+ BatchTranslatorContext<T> context,
+ ParameterBinding[] bindings,
+ BatchQueryRow row);
+
+ protected String doTranslate(BatchTranslatorContext<T> context, NodeBuilder nodeBuilder) {
+ Node node = context.getAdapter().getSqlTreeProcessor().process(nodeBuilder.build());
+
SQLGenerationVisitor visitor = new SQLGenerationVisitor(new DefaultQuotingAppendable(context));
node.visit(visitor);
- bindings = context.getBindings().toArray(new ParameterBinding[0]);
return visitor.getSQLString();
}
- abstract protected boolean isNullAttribute(DbAttribute attribute);
+ protected abstract boolean isNullAttribute(BatchTranslatorContext<T> context, DbAttribute attribute);
- protected ExpressionNodeBuilder buildQualifier(List<DbAttribute> attributeList) {
+ protected ExpressionNodeBuilder buildQualifier(BatchTranslatorContext<T> context, List<DbAttribute> attributeList) {
ExpressionNodeBuilder eq = null;
for (DbAttribute attr : attributeList) {
- Integer value = isNullAttribute(attr) ? null : 1;
+ Integer value = isNullAttribute(context, attr) ? null : 1;
ExpressionNodeBuilder next = SQLBuilder
.column(attr.getName()).attribute(attr)
.eq(SQLBuilder.value(value).attribute(attr));
- if(eq == null) {
+ if (eq == null) {
eq = next;
} else {
eq = eq.and(next);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchRowBinder.java
similarity index 66%
rename from cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchRowBinder.java
index 951ef9482..f0f8a3329 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchRowBinder.java
@@ -16,21 +16,21 @@
* specific language governing permissions and limitations
* under the License.
****************************************************************/
+
package org.apache.cayenne.access.translator.batch;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.query.BatchQueryRow;
/**
- * Factory which creates BatchQueryBuilders for different types of queries,
- * which, in their turn, create SQL strings for batch queries.
- *
- * @since 4.0
+ * A stateless strategy that populates a batch query's binding template with the values of a single
+ * {@link BatchQueryRow}. The same template array is reused for every row, so the returned array is the
+ * one passed in, only with the per-row state applied.
+ *
+ * @since 5.0
*/
-public interface BatchTranslatorFactory {
+@FunctionalInterface
+public interface BatchRowBinder {
- /**
- * Creates a proper translator for a BatchQuery
- */
- BatchTranslator translator(BatchQuery query, DbAdapter adapter, String trimFunction);
+ ParameterBinding[] bind(ParameterBinding[] bindings, BatchQueryRow row);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java
index 73a75fdbc..d6150c1b0 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java
@@ -19,33 +19,45 @@
package org.apache.cayenne.access.translator.batch;
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.query.BatchQueryRow;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.query.BatchQuery;
/**
- * Superclass of batch query translators.
- *
+ * A stateless service that translates a batch query of type {@code T} into an immutable
+ * {@link TranslatedBatch}. Each batch query flavor (insert, update, delete) is handled by its own
+ * translator, configured individually in the DI container under the {@link #INSERT}, {@link #UPDATE}
+ * and {@link #DELETE} binding names.
+ *
+ * @param <T> type of the batch query to translate
* @since 4.0
*/
-public interface BatchTranslator {
+public interface BatchTranslator<T extends BatchQuery> {
+
+ /**
+ * DI binding name of the translator for {@link org.apache.cayenne.query.InsertBatchQuery}.
+ *
+ * @since 5.0
+ */
+ String INSERT = "insert";
/**
- * Returns SQL String that can be used to init a PreparedStatement.
+ * DI binding name of the translator for {@link org.apache.cayenne.query.UpdateBatchQuery}.
+ *
+ * @since 5.0
*/
- String getSql();
+ String UPDATE = "update";
/**
- * Returns the widest possible array of bindings for this query.
+ * DI binding name of the translator for {@link org.apache.cayenne.query.DeleteBatchQuery}.
+ *
+ * @since 5.0
*/
- ParameterBinding[] getBindings();
+ String DELETE = "delete";
/**
- * Updates internal bindings to be used with a given row, returning updated
- * bindings array. This method guarantees that the returned array contains
- * the same bindings in the same order as in the array returned from
- * {@link #getBindings()} (but in a state corresponding to the 'row'
- * parameter). Usually the returned array is actually the same object reused
- * for every iteration, only with changed object state.
+ * Translates the provided batch query into an immutable {@link TranslatedBatch}.
+ *
+ * @since 5.0
*/
- ParameterBinding[] updateBindings(BatchQueryRow row);
+ TranslatedBatch translate(T query, DbAdapter adapter);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DefaultBatchTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DefaultBatchTranslatorFactory.java
deleted file mode 100644
index 56ff01969..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DefaultBatchTranslatorFactory.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-package org.apache.cayenne.access.translator.batch;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.DeleteBatchQuery;
-import org.apache.cayenne.query.InsertBatchQuery;
-import org.apache.cayenne.query.UpdateBatchQuery;
-
-/**
- * Default implementation of {@link BatchTranslatorFactory}.
- *
- * @since 4.2
- */
-public class DefaultBatchTranslatorFactory implements BatchTranslatorFactory {
-
- @Override
- public BatchTranslator translator(BatchQuery query, DbAdapter adapter, String trimFunction) {
- return switch (query) {
- case InsertBatchQuery insertBatchQuery -> insertTranslator(insertBatchQuery, adapter);
- case UpdateBatchQuery updateBatchQuery -> updateTranslator(updateBatchQuery, adapter);
- case DeleteBatchQuery deleteBatchQuery -> deleteTranslator(deleteBatchQuery, adapter);
- case null, default -> throw new CayenneRuntimeException("Unsupported batch query: %s", query);
- };
- }
-
- protected BatchTranslator deleteTranslator(DeleteBatchQuery query, DbAdapter adapter) {
- return new DeleteBatchTranslator(query, adapter);
- }
-
- protected BatchTranslator insertTranslator(InsertBatchQuery query, DbAdapter adapter) {
- return new InsertBatchTranslator(query, adapter);
- }
-
- protected BatchTranslator updateTranslator(UpdateBatchQuery query, DbAdapter adapter) {
- return new UpdateBatchTranslator(query, adapter);
- }
-
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
index 414b86cbb..830a3e7af 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
@@ -23,7 +23,6 @@ import org.apache.cayenne.access.sqlbuilder.DeleteBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQueryRow;
import org.apache.cayenne.query.DeleteBatchQuery;
@@ -31,37 +30,41 @@ import org.apache.cayenne.query.DeleteBatchQuery;
/**
* @since 4.2
*/
-public class DeleteBatchTranslator extends BaseBatchTranslator<DeleteBatchQuery> implements BatchTranslator {
-
- public DeleteBatchTranslator(DeleteBatchQuery query, DbAdapter adapter) {
- super(query, adapter);
- }
+public class DeleteBatchTranslator extends BaseBatchTranslator<DeleteBatchQuery> {
@Override
- public String getSql() {
+ protected String createSql(BatchTranslatorContext<DeleteBatchQuery> context) {
DeleteBuilder deleteBuilder = SQLBuilder
.delete(context.getRootDbEntity())
- .where(buildQualifier(context.getQuery().getDbAttributes()));
- return doTranslate(deleteBuilder);
+ .where(buildQualifier(context, context.getQuery().getDbAttributes()));
+ return doTranslate(context, deleteBuilder);
}
@Override
- protected boolean isNullAttribute(DbAttribute attribute) {
+ protected boolean isNullAttribute(BatchTranslatorContext<DeleteBatchQuery> context, DbAttribute attribute) {
return context.getQuery().isNull(attribute);
}
@Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
+ protected ParameterBinding[] updateBindings(
+ BatchTranslatorContext<DeleteBatchQuery> context,
+ ParameterBinding[] bindings,
+ BatchQueryRow row) {
+
DeleteBatchQuery deleteBatch = context.getQuery();
- for(int i=0, position=0; i<deleteBatch.getDbAttributes().size(); i++) {
- position = updateBinding(row.getValue(i), position);
+ for (int i = 0, position = 0; i < deleteBatch.getDbAttributes().size(); i++) {
+ position = updateBinding(context, bindings, row.getValue(i), position);
}
return bindings;
}
- protected int updateBinding(Object value, int position) {
+ protected int updateBinding(
+ BatchTranslatorContext<DeleteBatchQuery> context,
+ ParameterBinding[] bindings,
+ Object value, int position) {
+
// skip null attributes... they are translated as "IS NULL"
- if(value != null) {
+ if (value != null) {
ExtendedType<?> extendedType = context.getAdapter().getExtendedTypes().getRegisteredType(value.getClass());
bindings[position].reset(++position, value, extendedType);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
index 2330ef872..f67545e26 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
@@ -23,7 +23,6 @@ import org.apache.cayenne.access.sqlbuilder.InsertBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQueryRow;
import org.apache.cayenne.query.InsertBatchQuery;
@@ -31,20 +30,16 @@ import org.apache.cayenne.query.InsertBatchQuery;
/**
* @since 4.2
*/
-public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery> implements BatchTranslator {
-
- public InsertBatchTranslator(InsertBatchQuery query, DbAdapter adapter) {
- super(query, adapter);
- }
+public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery> {
@Override
- public String getSql() {
+ protected String createSql(BatchTranslatorContext<InsertBatchQuery> context) {
InsertBatchQuery query = context.getQuery();
InsertBuilder insertBuilder = SQLBuilder.insert(context.getRootDbEntity());
for(DbAttribute attribute : query.getDbAttributes()) {
// skip generated attributes, if needed
- if(excludeInBatch(attribute)) {
+ if(excludeInBatch(context, attribute)) {
continue;
}
insertBuilder
@@ -54,16 +49,17 @@ public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery>
.value(SQLBuilder.value(1).attribute(attribute));
}
- return doTranslate(insertBuilder);
+ return doTranslate(context, insertBuilder);
}
@Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
+ protected ParameterBinding[] updateBindings(BatchTranslatorContext<InsertBatchQuery> context,
+ ParameterBinding[] bindings, BatchQueryRow row) {
InsertBatchQuery query = context.getQuery();
int i=0;
int j=0;
for(DbAttribute attribute : query.getDbAttributes()) {
- if(excludeInBatch(attribute)) {
+ if(excludeInBatch(context, attribute)) {
i++;
continue;
}
@@ -77,7 +73,7 @@ public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery>
return bindings;
}
- protected boolean excludeInBatch(DbAttribute attribute) {
+ protected boolean excludeInBatch(BatchTranslatorContext<InsertBatchQuery> context, DbAttribute attribute) {
// attribute inclusion rule - one of the rules below must be true:
// (1) attribute not generated
// (2) attribute is generated and PK and adapter does not support generated keys
@@ -85,7 +81,7 @@ public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery>
}
@Override
- protected boolean isNullAttribute(DbAttribute attribute) {
+ protected boolean isNullAttribute(BatchTranslatorContext<InsertBatchQuery> context, DbAttribute attribute) {
return false;
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
index d866fdadf..ced812e00 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
@@ -23,51 +23,85 @@ import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.sqlbuilder.UpdateBuilder;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQueryRow;
import org.apache.cayenne.query.DeleteBatchQuery;
+import java.sql.Types;
+
import static org.apache.cayenne.access.sqlbuilder.SQLBuilder.*;
/**
+ * A delete {@link BatchTranslator} that performs a 'soft' delete (an UPDATE setting the 'deleted' field
+ * to true) for entities that have a boolean 'deleted' field, and falls back to the regular SQL DELETE of
+ * the {@link DeleteBatchTranslator} superclass for the rest. Bind it under the {@link BatchTranslator#DELETE}
+ * name to enable soft deletes.
+ *
* @since 4.2
*/
public class SoftDeleteBatchTranslator extends DeleteBatchTranslator {
+ public static final String DEFAULT_DELETED_FIELD_NAME = "DELETED";
+
private final String deletedFieldName;
- public SoftDeleteBatchTranslator(DeleteBatchQuery query, DbAdapter adapter, String deletedFieldName) {
- super(query, adapter);
+ public SoftDeleteBatchTranslator() {
+ this(DEFAULT_DELETED_FIELD_NAME);
+ }
+
+ public SoftDeleteBatchTranslator(String deletedFieldName) {
this.deletedFieldName = deletedFieldName;
}
+ protected boolean isHardDelete(DeleteBatchQuery query) {
+ DbAttribute attr = query.getDbEntity().getAttribute(deletedFieldName);
+ return attr == null || attr.getType() != Types.BOOLEAN;
+ }
+
@Override
- public String getSql() {
+ protected String createSql(BatchTranslatorContext<DeleteBatchQuery> context) {
DeleteBatchQuery query = context.getQuery();
- DbAttribute deleteAttribute = query.getDbEntity().getAttribute(deletedFieldName);
+ if (isHardDelete(query)) {
+ return super.createSql(context);
+ }
+ DbAttribute deleteAttribute = query.getDbEntity().getAttribute(deletedFieldName);
UpdateBuilder updateBuilder = update(context.getRootDbEntity())
.set(column(deletedFieldName).attribute(deleteAttribute)
.eq(SQLBuilder.value(true).attribute(deleteAttribute)))
- .where(buildQualifier(query.getDbAttributes()));
+ .where(buildQualifier(context, query.getDbAttributes()));
+
+ return doTranslate(context, updateBuilder);
+ }
- String sql = doTranslate(updateBuilder);
+ @Override
+ protected ParameterBinding[] createBindings(BatchTranslatorContext<DeleteBatchQuery> context) {
+ ParameterBinding[] bindings = super.createBindings(context);
+ if (isHardDelete(context.getQuery())) {
+ return bindings;
+ }
+ // the 'deleted' flag is the first binding and stays constant across all rows of the batch
+ DbAttribute deleteAttribute = context.getQuery().getDbEntity().getAttribute(deletedFieldName);
String typeName = TypesMapping.getJavaBySqlType(deleteAttribute);
ExtendedType<?> extendedType = context.getAdapter().getExtendedTypes().getRegisteredType(typeName);
bindings[0].reset(1, true, extendedType);
- return sql;
+ return bindings;
}
@Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
+ protected ParameterBinding[] updateBindings(BatchTranslatorContext<DeleteBatchQuery> context,
+ ParameterBinding[] bindings, BatchQueryRow row) {
DeleteBatchQuery deleteBatch = context.getQuery();
+ if (isHardDelete(deleteBatch)) {
+ return super.updateBindings(context, bindings, row);
+ }
+ // bindings[0] holds the constant 'deleted' flag, so qualifier values start at position 1
for(int i=0, position=1; i<deleteBatch.getDbAttributes().size(); i++) {
- position = updateBinding(row.getValue(i), position);
+ position = updateBinding(context, bindings, row.getValue(i), position);
}
return bindings;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteTranslatorFactory.java
deleted file mode 100644
index c0eec5aad..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteTranslatorFactory.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-package org.apache.cayenne.access.translator.batch;
-
-import java.sql.Types;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.query.DeleteBatchQuery;
-
-/**
- * Implementation of {link #BatchTranslator}, which uses 'soft' delete
- * (runs UPDATE and sets 'deleted' field to true instead-of running SQL DELETE)
- *
- * @since 4.2
- */
-public class SoftDeleteTranslatorFactory extends DefaultBatchTranslatorFactory {
- /**
- * Default name of 'deleted' field
- */
- public static final String DEFAULT_DELETED_FIELD_NAME = "DELETED";
-
- /**
- * Name of 'deleted' field
- */
- private String deletedFieldName;
-
- public SoftDeleteTranslatorFactory() {
- this(DEFAULT_DELETED_FIELD_NAME);
- }
-
- public SoftDeleteTranslatorFactory(String deletedFieldName) {
- this.deletedFieldName = deletedFieldName;
- }
-
- @Override
- protected BatchTranslator deleteTranslator(DeleteBatchQuery query, DbAdapter adapter) {
-
- DbAttribute attr = query.getDbEntity().getAttribute(deletedFieldName);
- boolean needsSoftDelete = attr != null && attr.getType() == Types.BOOLEAN;
-
- return needsSoftDelete
- ? new SoftDeleteBatchTranslator(query, adapter, deletedFieldName)
- : super.deleteTranslator(query, adapter);
- }
-
- /**
- * @return name of 'deleted' field
- */
- public String getDeletedFieldName() {
- return deletedFieldName;
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleBatchAction.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/TranslatedBatch.java
similarity index 57%
rename from cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleBatchAction.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/batch/TranslatedBatch.java
index f70d2a95e..4c81af7b2 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleBatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/TranslatedBatch.java
@@ -17,27 +17,24 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.dba.oracle;
+package org.apache.cayenne.access.translator.batch;
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.jdbc.BatchAction;
-import org.apache.cayenne.access.translator.batch.BatchTranslator;
-import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.query.BatchQueryRow;
/**
- * @since 1.2
+ * An immutable result of translating a batch query: the SQL String shared by all rows of the batch,
+ * the widest possible array of parameter bindings, and a stateless {@link BatchRowBinder} that applies
+ * a single row's state to those bindings.
+ *
+ * @since 5.0
*/
-class OracleBatchAction extends BatchAction {
+public record TranslatedBatch(String sql, ParameterBinding[] bindings, BatchRowBinder binder) {
/**
- * @since 4.0
+ * Applies the given row's state to the binding template, returning the (reused) bindings array.
*/
- OracleBatchAction(BatchQuery batchQuery, DataNode dataNode, boolean runningAsBatch) {
- super(batchQuery, dataNode, runningAsBatch);
- }
-
- @Override
- protected BatchTranslator createTranslator() {
- return dataNode.batchTranslator(query, OracleAdapter.TRIM_FUNCTION);
+ public ParameterBinding[] updateBindings(BatchQueryRow row) {
+ return binder.bind(bindings, row);
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
index 6c9eca408..7adf35a0a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
@@ -23,7 +23,6 @@ import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.sqlbuilder.UpdateBuilder;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQueryRow;
import org.apache.cayenne.query.UpdateBatchQuery;
@@ -31,14 +30,10 @@ import org.apache.cayenne.query.UpdateBatchQuery;
/**
* @since 4.2
*/
-public class UpdateBatchTranslator extends BaseBatchTranslator<UpdateBatchQuery> implements BatchTranslator {
-
- public UpdateBatchTranslator(UpdateBatchQuery query, DbAdapter adapter) {
- super(query, adapter);
- }
+public class UpdateBatchTranslator extends BaseBatchTranslator<UpdateBatchQuery> {
@Override
- public String getSql() {
+ protected String createSql(BatchTranslatorContext<UpdateBatchQuery> context) {
UpdateBatchQuery query = context.getQuery();
UpdateBuilder updateBuilder = SQLBuilder.update(context.getRootDbEntity());
@@ -48,18 +43,19 @@ public class UpdateBatchTranslator extends BaseBatchTranslator<UpdateBatchQuery>
.eq(SQLBuilder.value(1).attribute(attr))
);
}
- updateBuilder.where(buildQualifier(query.getQualifierAttributes()));
+ updateBuilder.where(buildQualifier(context, query.getQualifierAttributes()));
- return doTranslate(updateBuilder);
+ return doTranslate(context, updateBuilder);
}
@Override
- protected boolean isNullAttribute(DbAttribute attribute) {
+ protected boolean isNullAttribute(BatchTranslatorContext<UpdateBatchQuery> context, DbAttribute attribute) {
return context.getQuery().isNull(attribute);
}
@Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
+ protected ParameterBinding[] updateBindings(BatchTranslatorContext<UpdateBatchQuery> context,
+ ParameterBinding[] bindings, BatchQueryRow row) {
UpdateBatchQuery updateBatch = context.getQuery();
int i = 0;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslator.java
deleted file mode 100644
index aa8435253..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslator.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-package org.apache.cayenne.access.translator.batch.legacy;
-
-import java.sql.Types;
-
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.batch.BatchTranslator;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.BatchQueryRow;
-
-/**
- * Superclass of batch query translators.
- *
- * @since 4.0
- * @deprecated since 4.2
- */
-@Deprecated(since = "4.2")
-public abstract class DefaultBatchTranslator implements BatchTranslator {
-
- protected BatchQuery query;
- protected DbAdapter adapter;
- protected String trimFunction;
-
- protected boolean translated;
- protected String sql;
- protected ParameterBinding[] bindings;
-
- public DefaultBatchTranslator(BatchQuery query, DbAdapter adapter, String trimFunction) {
- this.query = query;
- this.adapter = adapter;
- this.trimFunction = trimFunction;
- }
-
- protected void ensureTranslated() {
- if (!translated) {
- this.sql = createSql();
- this.bindings = createBindings();
- translated = true;
- }
- }
-
- /**
- * Translates BatchQuery into an SQL string formatted to use in a
- * PreparedStatement.
- */
- @Override
- public String getSql() {
- ensureTranslated();
- return sql;
- }
-
- @Override
- public ParameterBinding[] getBindings() {
- ensureTranslated();
- return bindings;
- }
-
- @Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
- ensureTranslated();
- return doUpdateBindings(row);
- }
-
- protected abstract String createSql();
-
- protected abstract ParameterBinding[] createBindings();
-
- protected abstract ParameterBinding[] doUpdateBindings(BatchQueryRow row);
-
- /**
- * Appends the name of the column to the query buffer. Subclasses use this
- * method to append column names in the WHERE clause, i.e. for the columns
- * that are not being updated.
- */
- protected void appendDbAttribute(StringBuilder buf, DbAttribute dbAttribute) {
-
- // TODO: (Andrus) is there a need for trimming binary types?
- boolean trim = dbAttribute.getType() == Types.CHAR && trimFunction != null;
- if (trim) {
- buf.append(trimFunction).append('(');
- }
-
- QuotingStrategy strategy = adapter.getQuotingStrategy();
-
- buf.append(strategy.quotedName(dbAttribute));
-
- if (trim) {
- buf.append(')');
- }
- }
-
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
index 50dc4f8df..562ba503c 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
@@ -38,8 +38,10 @@ import org.apache.cayenne.access.flush.operation.DefaultDbRowOpSorter;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.access.jdbc.reader.DefaultRowReaderFactory;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
-import org.apache.cayenne.access.translator.batch.DefaultBatchTranslatorFactory;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator;
+import org.apache.cayenne.access.translator.batch.InsertBatchTranslator;
+import org.apache.cayenne.access.translator.batch.UpdateBatchTranslator;
import org.apache.cayenne.access.translator.select.DbAdapterDelegatedSelectTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.*;
@@ -461,7 +463,9 @@ public class CoreModule implements Module {
// configured by the owning domain
binder.bind(EntitySorter.class).to(AshwoodEntitySorter.class).withoutScope();
- binder.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).to(InsertBatchTranslator.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).to(UpdateBatchTranslator.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).to(DeleteBatchTranslator.class);
binder.bind(SelectTranslator.class).to(DbAdapterDelegatedSelectTranslator.class);
// a default ObjectMapRetainStrategy used to create objects map for
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
index 765e3a2e7..fa818cd2e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
@@ -22,8 +22,11 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.dbsync.SchemaUpdateStrategyFactory;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
+import org.apache.cayenne.query.DeleteBatchQuery;
+import org.apache.cayenne.query.InsertBatchQuery;
+import org.apache.cayenne.query.UpdateBatchQuery;
import org.apache.cayenne.configuration.DataNodeDescriptor;
import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.Inject;
@@ -45,9 +48,15 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
@Inject
protected DataSourceFactory dataSourceFactory;
- @Inject
- protected BatchTranslatorFactory batchTranslatorFactory;
-
+ @Inject(BatchTranslator.INSERT)
+ protected BatchTranslator<InsertBatchQuery> insertBatchTranslator;
+
+ @Inject(BatchTranslator.UPDATE)
+ protected BatchTranslator<UpdateBatchQuery> updateBatchTranslator;
+
+ @Inject(BatchTranslator.DELETE)
+ protected BatchTranslator<DeleteBatchQuery> deleteBatchTranslator;
+
@Inject
protected SelectTranslator selectTranslator;
@@ -70,7 +79,9 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
dataNode.setJdbcEventLogger(jdbcEventLogger);
dataNode.setRowReaderFactory(rowReaderFactory);
- dataNode.setBatchTranslatorFactory(batchTranslatorFactory);
+ dataNode.setInsertBatchTranslator(insertBatchTranslator);
+ dataNode.setUpdateBatchTranslator(updateBatchTranslator);
+ dataNode.setDeleteBatchTranslator(deleteBatchTranslator);
dataNode.setSelectTranslator(selectTranslator);
dataNode.setSqlTemplateTranslator(sqlTemplateTranslator);
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java
index 94fa21547..02537b827 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java
@@ -21,7 +21,6 @@ package org.apache.cayenne.dba.oracle;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.JdbcActionBuilder;
-import org.apache.cayenne.query.BatchQuery;
import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.SQLAction;
@@ -41,18 +40,6 @@ class OracleActionBuilder extends JdbcActionBuilder {
return new OracleSQLTemplateAction(query, dataNode);
}
- @Override
- public SQLAction batchAction(BatchQuery query) {
-
- // optimistic locking is not supported in batches due to JDBC driver
- // limitations
- // TODO: is this still true with ojdbc6.jar?
- boolean useOptimisticLock = query.isUsingOptimisticLocking();
- boolean runningAsBatch = !useOptimisticLock && dataNode.getAdapter().supportsBatchUpdates();
-
- return new OracleBatchAction(query, dataNode, runningAsBatch);
- }
-
@Override
public SQLAction procedureAction(ProcedureQuery query) {
return new OracleProcedureAction(query, dataNode);
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java
index 87fb2996d..5ecf042d6 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.access.MockOperationObserver;
import org.apache.cayenne.access.OptimisticLockException;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator;
+import org.apache.cayenne.access.translator.batch.TranslatedBatch;
import org.apache.cayenne.dba.JdbcAdapter;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
@@ -72,7 +73,7 @@ public class BatchActionLockingIT {
batchQuery.setUsingOptimisticLocking(true);
batchQuery.add(qualifierSnapshot);
- DeleteBatchTranslator batchQueryBuilder = new DeleteBatchTranslator(batchQuery, adapter);
+ TranslatedBatch translated = new DeleteBatchTranslator().translate(batchQuery, adapter);
TestConnection mockConnection = new TestConnection();
mockConnection.prepareUpdateCount("DELETE", 1);
@@ -84,7 +85,7 @@ public class BatchActionLockingIT {
node.setEntityResolver(resolver);
node.setRowReaderFactory(mock(RowReaderFactory.class));
BatchAction action = new BatchAction(batchQuery, node, false);
- action.runAsIndividualQueries(mockConnection, batchQueryBuilder, new MockOperationObserver(), generatesKeys);
+ action.runAsIndividualQueries(mockConnection, translated, new MockOperationObserver(), generatesKeys);
assertEquals(0, mockConnection.getNumberCommits());
assertEquals(0, mockConnection.getNumberRollbacks());
}
@@ -110,7 +111,7 @@ public class BatchActionLockingIT {
batchQuery.setUsingOptimisticLocking(true);
batchQuery.add(qualifierSnapshot);
- DeleteBatchTranslator batchQueryBuilder = new DeleteBatchTranslator(batchQuery, adapter);
+ TranslatedBatch translated = new DeleteBatchTranslator().translate(batchQuery, adapter);
TestConnection mockConnection = new TestConnection();
mockConnection.prepareUpdateCount("DELETE", 0);
@@ -122,7 +123,7 @@ public class BatchActionLockingIT {
node.setRowReaderFactory(mock(RowReaderFactory.class));
BatchAction action = new BatchAction(batchQuery, node, false);
assertThrows(OptimisticLockException.class, () ->
- action.runAsIndividualQueries(mockConnection, batchQueryBuilder, new MockOperationObserver(), generatesKeys));
+ action.runAsIndividualQueries(mockConnection, translated, new MockOperationObserver(), generatesKeys));
assertEquals(0, mockConnection.getNumberCommits());
assertEquals(0, mockConnection.getNumberRollbacks());
}
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslatorIT.java
index 6814d1f8d..ba646a9a1 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslatorIT.java
@@ -40,7 +40,6 @@ import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.mock;
public class DeleteBatchTranslatorIT {
@@ -61,17 +60,6 @@ public class DeleteBatchTranslatorIT {
objectFactory = env.adhocObjectFactory();
}
- @Test
- public void constructor() {
- DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
-
- DeleteBatchQuery query = mock(DeleteBatchQuery.class);
- DeleteBatchTranslator builder = new DeleteBatchTranslator(query, adapter);
-
- assertSame(adapter, builder.context.getAdapter());
- assertSame(query, builder.context.getQuery());
- }
-
@Test
public void createSqlString() {
DbEntity entity = runtime.getDataDomain().getEntityResolver().getObjEntity(SimpleLockingTestEntity.class)
@@ -82,8 +70,7 @@ public class DeleteBatchTranslatorIT {
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, Collections.emptySet(), 1);
DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- DeleteBatchTranslator builder = new DeleteBatchTranslator(deleteQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new DeleteBatchTranslator().translate(deleteQuery, adapter).sql();
assertNotNull(generatedSql);
assertEquals("DELETE FROM " + entity.getName() + " WHERE LOCKING_TEST_ID = ?", generatedSql);
}
@@ -101,8 +88,7 @@ public class DeleteBatchTranslatorIT {
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, nullAttributes, 1);
DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- DeleteBatchTranslator builder = new DeleteBatchTranslator(deleteQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new DeleteBatchTranslator().translate(deleteQuery, adapter).sql();
assertNotNull(generatedSql);
assertEquals("DELETE FROM " + entity.getName() + " WHERE ( LOCKING_TEST_ID = ? ) AND ( NAME IS NULL )", generatedSql);
}
@@ -117,8 +103,7 @@ public class DeleteBatchTranslatorIT {
List<DbAttribute> idAttributes = Collections.singletonList(entity.getAttribute("LOCKING_TEST_ID"));
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, Collections.emptySet(), 1);
- DeleteBatchTranslator builder = new DeleteBatchTranslator(deleteQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new DeleteBatchTranslator().translate(deleteQuery, adapter).sql();
String charStart = unitAdapter.getIdentifiersStartQuote();
String charEnd = unitAdapter.getIdentifiersEndQuote();
@@ -147,8 +132,7 @@ public class DeleteBatchTranslatorIT {
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, nullAttributes, 1);
- DeleteBatchTranslator builder = new DeleteBatchTranslator(deleteQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new DeleteBatchTranslator().translate(deleteQuery, adapter).sql();
String charStart = unitAdapter.getIdentifiersStartQuote();
String charEnd = unitAdapter.getIdentifiersEndQuote();
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslatorIT.java
index 4efb2566f..fcd4e7a9f 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslatorIT.java
@@ -34,8 +34,6 @@ import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.mockito.Mockito.mock;
public class InsertBatchTranslatorIT {
@@ -56,17 +54,6 @@ public class InsertBatchTranslatorIT {
objectFactory = env.adhocObjectFactory();
}
- @Test
- public void constructor() {
- DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
-
- InsertBatchQuery query = mock(InsertBatchQuery.class);
- InsertBatchTranslator builder = new InsertBatchTranslator(query, adapter);
-
- assertSame(adapter, builder.context.getAdapter());
- assertSame(query, builder.context.getQuery());
- }
-
@Test
public void createSqlString() {
DbEntity entity = runtime.getDataDomain().getEntityResolver()
@@ -75,8 +62,7 @@ public class InsertBatchTranslatorIT {
DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
InsertBatchQuery insertQuery = new InsertBatchQuery(entity, 1);
- InsertBatchTranslator builder = new InsertBatchTranslator(insertQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new InsertBatchTranslator().translate(insertQuery, adapter).sql();
assertNotNull(generatedSql);
assertEquals("INSERT INTO " + entity.getName() + "( DESCRIPTION, INT_COLUMN_NOTNULL, INT_COLUMN_NULL, LOCKING_TEST_ID, NAME) " +
"VALUES( ?, ?, ?, ?, ?)",
@@ -92,8 +78,7 @@ public class InsertBatchTranslatorIT {
entity.getDataMap().setQuotingSQLIdentifiers(true);
InsertBatchQuery insertQuery = new InsertBatchQuery(entity, 1);
- InsertBatchTranslator builder = new InsertBatchTranslator(insertQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new InsertBatchTranslator().translate(insertQuery, adapter).sql();
String charStart = unitAdapter.getIdentifiersStartQuote();
String charEnd = unitAdapter.getIdentifiersEndQuote();
assertNotNull(generatedSql);
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslatorIT.java
index c5cd3a691..b8ecf8423 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslatorIT.java
@@ -56,13 +56,13 @@ public class SoftDeleteBatchTranslatorIT {
private TestDbAdapter unitAdapter;
private AdhocObjectFactory objectFactory;
- private DeleteBatchTranslator createTranslator(DeleteBatchQuery query) {
+ private String createSql(DeleteBatchQuery query) {
DbAdapter adapter = objectFactory.newInstance(JdbcAdapter.class, JdbcAdapter.class.getName());
- return createTranslator(query, adapter);
+ return createSql(query, adapter);
}
- private DeleteBatchTranslator createTranslator(DeleteBatchQuery query, DbAdapter adapter) {
- return (DeleteBatchTranslator) new SoftDeleteTranslatorFactory().translator(query, adapter, null);
+ private String createSql(DeleteBatchQuery query, DbAdapter adapter) {
+ return new SoftDeleteBatchTranslator().translate(query, adapter).sql();
}
@BeforeEach
@@ -79,8 +79,7 @@ public class SoftDeleteBatchTranslatorIT {
List<DbAttribute> idAttributes = Collections.singletonList(entity.getAttribute("ID"));
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, Collections.emptySet(), 1);
- DeleteBatchTranslator builder = createTranslator(deleteQuery);
- String generatedSql = builder.getSql();
+ String generatedSql = createSql(deleteQuery);
assertNotNull(generatedSql);
assertEquals("UPDATE " + entity.getName() + " SET DELETED = ? WHERE ID = ?", generatedSql);
}
@@ -94,8 +93,7 @@ public class SoftDeleteBatchTranslatorIT {
Collection<String> nullAttributes = Collections.singleton("NAME");
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, nullAttributes, 1);
- DeleteBatchTranslator builder = createTranslator(deleteQuery);
- String generatedSql = builder.getSql();
+ String generatedSql = createSql(deleteQuery);
assertNotNull(generatedSql);
assertEquals("UPDATE " + entity.getName() + " SET DELETED = ? WHERE ( ID = ? ) AND ( NAME IS NULL )", generatedSql);
}
@@ -111,8 +109,7 @@ public class SoftDeleteBatchTranslatorIT {
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, Collections.emptySet(), 1);
DbAdapter adapter = node.getAdapter();
- DeleteBatchTranslator builder = createTranslator(deleteQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = createSql(deleteQuery, adapter);
String charStart = unitAdapter.getIdentifiersStartQuote();
String charEnd = unitAdapter.getIdentifiersEndQuote();
@@ -131,9 +128,9 @@ public class SoftDeleteBatchTranslatorIT {
DbEntity entity = env.context().getEntityResolver().getObjEntity(SoftDelete.class).getDbEntity();
- BatchTranslatorFactory oldFactory = node.getBatchTranslatorFactory();
+ BatchTranslator<DeleteBatchQuery> oldTranslator = node.getDeleteBatchTranslator();
try {
- node.setBatchTranslatorFactory(new SoftDeleteTranslatorFactory());
+ node.setDeleteBatchTranslator(new SoftDeleteBatchTranslator());
final SoftDelete test = env.context().newObject(SoftDelete.class);
test.setName("SoftDeleteBatchQueryBuilderTest");
@@ -169,7 +166,7 @@ public class SoftDeleteBatchTranslatorIT {
}.runTest(200);
} finally {
env.context().performQuery(new SQLTemplate(entity, "DELETE FROM SOFT_DELETE"));
- node.setBatchTranslatorFactory(oldFactory);
+ node.setDeleteBatchTranslator(oldTranslator);
}
}
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslatorIT.java
index 13150be93..053a03d22 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslatorIT.java
@@ -40,7 +40,6 @@ import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.mock;
public class UpdateBatchTranslatorIT {
@@ -61,16 +60,6 @@ public class UpdateBatchTranslatorIT {
objectFactory = env.adhocObjectFactory();
}
- @Test
- public void constructor() {
- DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- UpdateBatchQuery query = mock(UpdateBatchQuery.class);
- UpdateBatchTranslator builder = new UpdateBatchTranslator(query, adapter);
-
- assertSame(adapter, builder.context.getAdapter());
- assertSame(query, builder.context.getQuery());
- }
-
@Test
public void createSqlString() {
DbEntity entity = runtime.getDataDomain().getEntityResolver().getObjEntity(SimpleLockingTestEntity.class)
@@ -83,8 +72,7 @@ public class UpdateBatchTranslatorIT {
Collections.emptySet(), 1);
DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- UpdateBatchTranslator builder = new UpdateBatchTranslator(updateQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new UpdateBatchTranslator().translate(updateQuery, adapter).sql();
assertNotNull(generatedSql);
assertEquals("UPDATE " + entity.getName() + " SET DESCRIPTION = ? WHERE LOCKING_TEST_ID = ?", generatedSql);
}
@@ -103,8 +91,7 @@ public class UpdateBatchTranslatorIT {
UpdateBatchQuery updateQuery = new UpdateBatchQuery(entity, idAttributes, updatedAttributes, nullAttributes, 1);
DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- UpdateBatchTranslator builder = new UpdateBatchTranslator(updateQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new UpdateBatchTranslator().translate(updateQuery, adapter).sql();
assertNotNull(generatedSql);
assertEquals("UPDATE " + entity.getName() + " SET DESCRIPTION = ? WHERE ( LOCKING_TEST_ID = ? ) AND ( NAME IS NULL )",
@@ -123,8 +110,7 @@ public class UpdateBatchTranslatorIT {
UpdateBatchQuery updateQuery = new UpdateBatchQuery(entity, idAttributes, updatedAttributes, Collections.emptySet(), 1);
- UpdateBatchTranslator builder = new UpdateBatchTranslator(updateQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new UpdateBatchTranslator().translate(updateQuery, adapter).sql();
String charStart = unitAdapter.getIdentifiersStartQuote();
String charEnd = unitAdapter.getIdentifiersEndQuote();
@@ -153,8 +139,7 @@ public class UpdateBatchTranslatorIT {
UpdateBatchQuery updateQuery = new UpdateBatchQuery(entity, idAttributes, updatedAttributes, nullAttributes, 1);
- UpdateBatchTranslator builder = new UpdateBatchTranslator(updateQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new UpdateBatchTranslator().translate(updateQuery, adapter).sql();
assertNotNull(generatedSql);
String charStart = unitAdapter.getIdentifiersStartQuote();
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslatorIT.java
deleted file mode 100644
index 3db0aa773..000000000
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslatorIT.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-
-package org.apache.cayenne.access.translator.batch.legacy;
-
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.BatchQueryRow;
-import org.apache.cayenne.unit.CayenneProjects;
-import org.apache.cayenne.unit.CayenneTestsEnv;
-import org.junit.jupiter.api.extension.RegisterExtension;
-import org.junit.jupiter.api.Test;
-import java.sql.Types;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.mockito.Mockito.mock;
-
-@Deprecated
-public class DefaultBatchTranslatorIT {
-
- @RegisterExtension
- static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.TESTMAP_PROJECT);
-
- @Test
- public void constructor() throws Exception {
- DbAdapter adapter = env.adhocObjectFactory().newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- DefaultBatchTranslator builder = new DefaultBatchTranslator(mock(BatchQuery.class), adapter, null) {
- @Override
- protected String createSql() {
- return null;
- }
-
- @Override
- protected ParameterBinding[] createBindings() {
- return new ParameterBinding[0];
- }
-
- @Override
- protected ParameterBinding[] doUpdateBindings(BatchQueryRow row) {
- return new ParameterBinding[0];
- }
- };
-
- assertSame(adapter, builder.adapter);
- }
-
- @Test
- public void appendDbAttribute1() throws Exception {
- DbAdapter adapter = env.adhocObjectFactory().newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- String trimFunction = "testTrim";
-
- DefaultBatchTranslator builder = new DefaultBatchTranslator(mock(BatchQuery.class), adapter, trimFunction) {
-
- @Override
- protected String createSql() {
- return null;
- }
-
- @Override
- protected ParameterBinding[] createBindings() {
- return new ParameterBinding[0];
- }
-
- @Override
- protected ParameterBinding[] doUpdateBindings(BatchQueryRow row) {
- return new ParameterBinding[0];
- }
- };
-
- StringBuilder buf = new StringBuilder();
- DbEntity entity = new DbEntity("Test");
- DbAttribute attr = new DbAttribute("testAttr", Types.CHAR, null);
- attr.setEntity(entity);
- builder.appendDbAttribute(buf, attr);
- assertEquals("testTrim(testAttr)", buf.toString());
-
- buf = new StringBuilder();
- attr = new DbAttribute("testAttr", Types.VARCHAR, null);
- attr.setEntity(entity);
- builder.appendDbAttribute(buf, attr);
- assertEquals("testAttr", buf.toString());
- }
-
- @Test
- public void appendDbAttribute2() throws Exception {
- DbAdapter adapter = env.adhocObjectFactory().newInstance(DbAdapter.class, JdbcAdapter.class.getName());
-
- DefaultBatchTranslator builder = new DefaultBatchTranslator(mock(BatchQuery.class), adapter, null) {
- @Override
- protected String createSql() {
- return null;
- }
-
- @Override
- protected ParameterBinding[] createBindings() {
- return new ParameterBinding[0];
- }
-
- @Override
- protected ParameterBinding[] doUpdateBindings(BatchQueryRow row) {
- return new ParameterBinding[0];
- }
- };
-
- StringBuilder buf = new StringBuilder();
- DbEntity entity = new DbEntity("Test");
-
- DbAttribute attr = new DbAttribute("testAttr", Types.CHAR, null);
- attr.setEntity(entity);
- builder.appendDbAttribute(buf, attr);
- assertEquals("testAttr", buf.toString());
-
- buf = new StringBuilder();
- attr = new DbAttribute("testAttr", Types.VARCHAR, null);
- attr.setEntity(entity);
-
- builder.appendDbAttribute(buf, attr);
- assertEquals("testAttr", buf.toString());
- }
-}
diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
index 81c9b61f2..cf8ea1cd6 100644
--- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
@@ -32,8 +32,10 @@ import org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy;
import org.apache.cayenne.access.dbsync.ThrowOnPartialOrCreateSchemaStrategy;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
-import org.apache.cayenne.access.translator.batch.DefaultBatchTranslatorFactory;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator;
+import org.apache.cayenne.access.translator.batch.InsertBatchTranslator;
+import org.apache.cayenne.access.translator.batch.UpdateBatchTranslator;
import org.apache.cayenne.access.translator.select.DbAdapterDelegatedSelectTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
@@ -222,7 +224,9 @@ public class DataDomainProviderTest {
b.bind(DataChannelDescriptorLoader.class).toInstance(testLoader);
b.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
b.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- b.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).to(InsertBatchTranslator.class);
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).to(UpdateBatchTranslator.class);
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).to(DeleteBatchTranslator.class);
b.bind(SelectTranslator.class).to(DbAdapterDelegatedSelectTranslator.class);
b.bind(DataSourceFactory.class).toInstance(new MockDataSourceFactory());
diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java
index 75cf74369..06b48b562 100644
--- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java
@@ -18,7 +18,7 @@
****************************************************************/
package org.apache.cayenne.configuration.runtime;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
@@ -84,7 +84,9 @@ public class DefaultDbAdapterFactoryTest {
binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- binder.bind(BatchTranslatorFactory.class).toInstance(mock(BatchTranslatorFactory.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).toInstance(mock(BatchTranslator.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).toInstance(mock(BatchTranslator.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).toInstance(mock(BatchTranslator.class));
};
Injector injector = DIBootstrap.createInjector(testModule);
@@ -114,7 +116,9 @@ public class DefaultDbAdapterFactoryTest {
b.bind(ResourceLocator.class).to(ClassLoaderResourceLocator.class);
b.bind(Key.get(ResourceLocator.class, Constants.RESOURCE_LOCATOR)).to(ClassLoaderResourceLocator.class);
b.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- b.bind(BatchTranslatorFactory.class).toInstance(mock(BatchTranslatorFactory.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).toInstance(mock(BatchTranslator.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).toInstance(mock(BatchTranslator.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).toInstance(mock(BatchTranslator.class));
b.bind(ValueObjectTypeRegistry.class).to(DefaultValueObjectTypeRegistry.class);
};
@@ -149,7 +153,9 @@ public class DefaultDbAdapterFactoryTest {
b.bind(ResourceLocator.class).to(ClassLoaderResourceLocator.class);
b.bind(Key.get(ResourceLocator.class, Constants.RESOURCE_LOCATOR)).to(ClassLoaderResourceLocator.class);
b.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- b.bind(BatchTranslatorFactory.class).toInstance(mock(BatchTranslatorFactory.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).toInstance(mock(BatchTranslator.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).toInstance(mock(BatchTranslator.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).toInstance(mock(BatchTranslator.class));
b.bind(ValueObjectTypeRegistry.class).to(DefaultValueObjectTypeRegistry.class);
b.bind(ValueComparisonStrategyFactory.class).to(DefaultValueComparisonStrategyFactory.class);
@@ -189,7 +195,9 @@ public class DefaultDbAdapterFactoryTest {
binder.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- binder.bind(BatchTranslatorFactory.class).toInstance(mock(BatchTranslatorFactory.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).toInstance(mock(BatchTranslator.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).toInstance(mock(BatchTranslator.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).toInstance(mock(BatchTranslator.class));
};
Injector injector = DIBootstrap.createInjector(testModule);