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 2016/10/24 19:06:13 UTC
cayenne git commit: CAY-2125 SchemaUpdateStrategy doesn't work with
multiple DataNodes
Repository: cayenne
Updated Branches:
refs/heads/master c430014d1 -> 60fc4d267
CAY-2125 SchemaUpdateStrategy doesn't work with multiple DataNodes
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/60fc4d26
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/60fc4d26
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/60fc4d26
Branch: refs/heads/master
Commit: 60fc4d2678b3d57f7dd896e9c8d07b7029cf3572
Parents: c430014
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Mon Oct 24 14:47:54 2016 -0400
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Mon Oct 24 15:06:01 2016 -0400
----------------------------------------------------------------------
.../org/apache/cayenne/access/DataNode.java | 42 ++----
.../access/dbsync/BaseSchemaUpdateStrategy.java | 18 +--
.../access/dbsync/CreateIfNoSchemaStrategy.java | 125 ++++++++--------
.../DefaultSchemaUpdateStrategyFactory.java | 47 ++++++
.../access/dbsync/SchemaUpdateStrategy.java | 4 +-
.../dbsync/SchemaUpdateStrategyFactory.java | 31 ++++
.../access/dbsync/SkipSchemaUpdateStrategy.java | 6 +-
.../ThrowOnPartialOrCreateSchemaStrategy.java | 20 +--
.../dbsync/ThrowOnPartialSchemaStrategy.java | 144 +++++++++----------
.../server/DefaultDataNodeFactory.java | 22 +--
.../configuration/server/ServerModule.java | 11 +-
.../access/dbsync/SchemaUpdateStrategyBase.java | 19 ++-
.../access/dbsync/TstSchemaUpdateStrategy.java | 8 +-
.../server/DataDomainProviderTest.java | 7 +-
docs/doc/src/main/resources/RELEASE-NOTES.txt | 1 +
docs/doc/src/main/resources/UPGRADE.txt | 4 +
16 files changed, 273 insertions(+), 236 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java
index 66651be..5c09b49 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java
@@ -19,21 +19,8 @@
package org.apache.cayenne.access;
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.logging.Logger;
-
-import javax.sql.DataSource;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
-import org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.jdbc.RowDescriptor;
import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
@@ -58,6 +45,17 @@ import org.apache.cayenne.tx.BaseTransaction;
import org.apache.cayenne.tx.Transaction;
import org.apache.cayenne.util.ToStringBuilder;
+import javax.sql.DataSource;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
/**
* An abstraction of a single physical data storage. This is usually a database
* server, but can potentially be some other storage type like an LDAP server,
@@ -70,7 +68,6 @@ public class DataNode implements QueryEngine {
protected DbAdapter adapter;
protected String dataSourceLocation;
protected String dataSourceFactory;
- protected String schemaUpdateStrategyName;
protected EntityResolver entityResolver;
protected SchemaUpdateStrategy schemaUpdateStrategy;
protected Map<String, DataMap> dataMaps;
@@ -106,23 +103,6 @@ public class DataNode implements QueryEngine {
/**
* @since 3.0
*/
- public String getSchemaUpdateStrategyName() {
- if (schemaUpdateStrategyName == null) {
- schemaUpdateStrategyName = SkipSchemaUpdateStrategy.class.getName();
- }
- return schemaUpdateStrategyName;
- }
-
- /**
- * @since 3.0
- */
- public void setSchemaUpdateStrategyName(String schemaUpdateStrategyName) {
- this.schemaUpdateStrategyName = schemaUpdateStrategyName;
- }
-
- /**
- * @since 3.0
- */
public SchemaUpdateStrategy getSchemaUpdateStrategy() {
return schemaUpdateStrategy;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/BaseSchemaUpdateStrategy.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/BaseSchemaUpdateStrategy.java b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/BaseSchemaUpdateStrategy.java
index f4bf779..7158c5b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/BaseSchemaUpdateStrategy.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/BaseSchemaUpdateStrategy.java
@@ -18,10 +18,10 @@
****************************************************************/
package org.apache.cayenne.access.dbsync;
-import java.sql.SQLException;
-
import org.apache.cayenne.access.DataNode;
+import java.sql.SQLException;
+
/**
* @since 3.0
*/
@@ -31,18 +31,20 @@ public abstract class BaseSchemaUpdateStrategy implements SchemaUpdateStrategy {
protected volatile ThreadLocal<Boolean> threadRunInProgress;
public BaseSchemaUpdateStrategy() {
- super();
- threadRunInProgress = new ThreadLocal<Boolean>();
+
+ // this barrier is needed to prevent stack overflow in the same thread
+ // (getConnection/updateSchema/getConnection/...)
+ this.threadRunInProgress = new ThreadLocal<>();
+ this.threadRunInProgress.set(false);
}
- /**
- * @since 3.0
- */
+ @Override
public void updateSchema(DataNode dataNode) throws SQLException {
- if (!run && (threadRunInProgress.get() == null || !threadRunInProgress.get())) {
+ if (!run && !threadRunInProgress.get()) {
synchronized (this) {
if (!run) {
+
try {
threadRunInProgress.set(true);
processSchemaUpdate(dataNode);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/CreateIfNoSchemaStrategy.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/CreateIfNoSchemaStrategy.java b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/CreateIfNoSchemaStrategy.java
index 2d72493..bcf0010 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/CreateIfNoSchemaStrategy.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/CreateIfNoSchemaStrategy.java
@@ -18,14 +18,6 @@
****************************************************************/
package org.apache.cayenne.access.dbsync;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.DbGenerator;
@@ -34,73 +26,80 @@ import org.apache.cayenne.map.DbEntity;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
/**
* @since 3.0
*/
public class CreateIfNoSchemaStrategy extends BaseSchemaUpdateStrategy {
- final static Log logger = LogFactory.getLog(CreateIfNoSchemaStrategy.class);
+ private final static Log LOGGER = LogFactory.getLog(CreateIfNoSchemaStrategy.class);
+
- @Override
- protected void processSchemaUpdate(DataNode dataNode) throws SQLException {
+ @Override
+ protected void processSchemaUpdate(DataNode dataNode) throws SQLException {
- Map<String, Boolean> nameTables = getNameTablesInDB(dataNode);
- Collection<DbEntity> entities = dataNode.getEntityResolver().getDbEntities();
- boolean generate = true;
- Iterator<DbEntity> it = entities.iterator();
- while (it.hasNext()) {
- if (nameTables.get(it.next().getName()) != null) {
- generate = false;
- break;
- }
- }
+ Map<String, Boolean> nameTables = getNameTablesInDB(dataNode);
+ Collection<DbEntity> entities = dataNode.getEntityResolver().getDbEntities();
+ boolean generate = true;
+ Iterator<DbEntity> it = entities.iterator();
+ while (it.hasNext()) {
+ if (nameTables.get(it.next().getName()) != null) {
+ generate = false;
+ break;
+ }
+ }
- if (generate) {
- logger.info("No schema detected, will create mapped tables");
- generate(dataNode);
- } else {
- logger.info("Full or partial schema detected, skipping tables creation");
- }
- }
+ if (generate) {
+ LOGGER.info("No schema detected, will create mapped tables");
+ generate(dataNode);
+ } else {
+ LOGGER.info("Full or partial schema detected, skipping tables creation");
+ }
+ }
- private void generate(DataNode dataNode) {
- Collection<DataMap> map = dataNode.getDataMaps();
- Iterator<DataMap> iterator = map.iterator();
- while (iterator.hasNext()) {
- DbGenerator gen = new DbGenerator(dataNode.getAdapter(), iterator.next(), dataNode.getJdbcEventLogger());
- gen.setShouldCreateTables(true);
- gen.setShouldDropTables(false);
- gen.setShouldCreateFKConstraints(true);
- gen.setShouldCreatePKSupport(true);
- gen.setShouldDropPKSupport(false);
- try {
- gen.runGenerator(dataNode.getDataSource());
- } catch (Exception e) {
- throw new CayenneRuntimeException(e);
- }
- }
- }
+ private void generate(DataNode dataNode) {
+ Collection<DataMap> map = dataNode.getDataMaps();
+ Iterator<DataMap> iterator = map.iterator();
+ while (iterator.hasNext()) {
+ DbGenerator gen = new DbGenerator(dataNode.getAdapter(), iterator.next(), dataNode.getJdbcEventLogger());
+ gen.setShouldCreateTables(true);
+ gen.setShouldDropTables(false);
+ gen.setShouldCreateFKConstraints(true);
+ gen.setShouldCreatePKSupport(true);
+ gen.setShouldDropPKSupport(false);
+ try {
+ gen.runGenerator(dataNode.getDataSource());
+ } catch (Exception e) {
+ throw new CayenneRuntimeException(e);
+ }
+ }
+ }
- /**
- * Returns all the table names in database.
- *
- * @throws SQLException
- */
- protected Map<String, Boolean> getNameTablesInDB(DataNode dataNode) throws SQLException {
- String tableLabel = dataNode.getAdapter().tableTypeForTable();
- Map<String, Boolean> nameTables = new HashMap<>();
+ /**
+ * Returns all the table names in database.
+ */
+ protected Map<String, Boolean> getNameTablesInDB(DataNode dataNode) throws SQLException {
+ String tableLabel = dataNode.getAdapter().tableTypeForTable();
+ Map<String, Boolean> nameTables = new HashMap<>();
- try (Connection con = dataNode.getDataSource().getConnection();) {
+ try (Connection con = dataNode.getDataSource().getConnection();) {
- try (ResultSet rs = con.getMetaData().getTables(null, null, "%", new String[] { tableLabel });) {
+ try (ResultSet rs = con.getMetaData().getTables(null, null, "%", new String[]{tableLabel});) {
- while (rs.next()) {
- String name = rs.getString("TABLE_NAME");
- nameTables.put(name, false);
- }
- }
- }
+ while (rs.next()) {
+ String name = rs.getString("TABLE_NAME");
+ nameTables.put(name, false);
+ }
+ }
+ }
- return nameTables;
- }
+ return nameTables;
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/DefaultSchemaUpdateStrategyFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/DefaultSchemaUpdateStrategyFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/DefaultSchemaUpdateStrategyFactory.java
new file mode 100644
index 0000000..0ccbc5f
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/DefaultSchemaUpdateStrategyFactory.java
@@ -0,0 +1,47 @@
+/*
+ * 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
+ *
+ * http://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.dbsync;
+
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.di.AdhocObjectFactory;
+import org.apache.cayenne.di.Inject;
+
+/**
+ * @since 4.0
+ */
+public class DefaultSchemaUpdateStrategyFactory implements SchemaUpdateStrategyFactory {
+
+ @Inject
+ protected AdhocObjectFactory objectFactory;
+
+ @Override
+ public SchemaUpdateStrategy create(DataNodeDescriptor nodeDescriptor) {
+ String type = nodeDescriptor.getSchemaUpdateStrategyType();
+
+ if (type == null) {
+ return createDefaultStrategy();
+ }
+
+ return objectFactory.newInstance(SchemaUpdateStrategy.class, type);
+ }
+
+ protected SchemaUpdateStrategy createDefaultStrategy() {
+ return new SkipSchemaUpdateStrategy();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategy.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategy.java b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategy.java
index 8459ac0..44b8bef 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategy.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategy.java
@@ -18,10 +18,10 @@
****************************************************************/
package org.apache.cayenne.access.dbsync;
-import java.sql.SQLException;
-
import org.apache.cayenne.access.DataNode;
+import java.sql.SQLException;
+
/**
* A strategy for auto generating a database schema on the application startup.
*
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyFactory.java
new file mode 100644
index 0000000..0508042
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyFactory.java
@@ -0,0 +1,31 @@
+/*
+ * 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
+ *
+ * http://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.dbsync;
+
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+
+/**
+ * A factory for {@link SchemaUpdateStrategy} instances.
+ *
+ * @since 4.0
+ */
+public interface SchemaUpdateStrategyFactory {
+
+ SchemaUpdateStrategy create(DataNodeDescriptor nodeDescriptor);
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SkipSchemaUpdateStrategy.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SkipSchemaUpdateStrategy.java b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SkipSchemaUpdateStrategy.java
index 8a8f7b6..587c4b0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SkipSchemaUpdateStrategy.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/SkipSchemaUpdateStrategy.java
@@ -23,14 +23,12 @@ import org.apache.cayenne.access.DataNode;
/**
* A SchemaUpdateStrategy that does nothing. This is usually the default strategy, as in
* most cases DB schema management is outside the scope of Cayenne.
- *
+ *
* @since 3.0
*/
public class SkipSchemaUpdateStrategy implements SchemaUpdateStrategy {
- /**
- * @since 3.0
- */
+ @Override
public void updateSchema(DataNode dataNode) {
// does nothing
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/ThrowOnPartialOrCreateSchemaStrategy.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/ThrowOnPartialOrCreateSchemaStrategy.java b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/ThrowOnPartialOrCreateSchemaStrategy.java
index bc215a7..46ea944 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/ThrowOnPartialOrCreateSchemaStrategy.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/ThrowOnPartialOrCreateSchemaStrategy.java
@@ -18,11 +18,6 @@
****************************************************************/
package org.apache.cayenne.access.dbsync;
-import java.sql.SQLException;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.DbGenerator;
@@ -30,13 +25,18 @@ import org.apache.cayenne.map.DataMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
/**
* @since 3.0
*/
public class ThrowOnPartialOrCreateSchemaStrategy extends ThrowOnPartialSchemaStrategy {
- final static Log logger = LogFactory
- .getLog(ThrowOnPartialOrCreateSchemaStrategy.class);
+ private final static Log LOGGER = LogFactory.getLog(ThrowOnPartialOrCreateSchemaStrategy.class);
+
@Override
protected void processSchemaUpdate(
@@ -46,14 +46,14 @@ public class ThrowOnPartialOrCreateSchemaStrategy extends ThrowOnPartialSchemaSt
int entitiesSize) throws SQLException {
if (mergerOnlyTable.size() == 0 && errorMessage == null) {
- logger.info("Full schema is present");
+ LOGGER.info("Full schema is present");
}
else if (mergerOnlyTable.size() == entitiesSize) {
- logger.info("No schema detected, will create mapped tables");
+ LOGGER.info("No schema detected, will create mapped tables");
generate(dataNode);
}
else {
- logger.info("Error - partial schema detected");
+ LOGGER.info("Error - partial schema detected");
StringBuilder buffer = new StringBuilder("Schema mismatch detected");
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/ThrowOnPartialSchemaStrategy.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/ThrowOnPartialSchemaStrategy.java b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/ThrowOnPartialSchemaStrategy.java
index 051feab..4cf7304 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/ThrowOnPartialSchemaStrategy.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/dbsync/ThrowOnPartialSchemaStrategy.java
@@ -18,6 +18,12 @@
****************************************************************/
package org.apache.cayenne.access.dbsync;
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.access.DataNode;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
@@ -26,82 +32,74 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
/**
* @since 3.0
*/
public class ThrowOnPartialSchemaStrategy extends BaseSchemaUpdateStrategy {
- final static Log logger = LogFactory.getLog(ThrowOnPartialSchemaStrategy.class);
-
- /**
- * @since 3.0
- */
- @Override
- protected void processSchemaUpdate(DataNode dataNode) throws SQLException {
-
- SchemaAnalyzer analyzer = new SchemaAnalyzer();
-
- List<String> schemas = new ArrayList<String>();
- DatabaseMetaData md = null;
- try {
-
- try (Connection connection = dataNode.getDataSource().getConnection();) {
- md = connection.getMetaData();
-
- try (ResultSet rs = md.getSchemas();) {
- while (rs.next()) {
- String schemaName = rs.getString(1);
- schemas.add(schemaName);
- }
- }
- }
-
- analyzer.analyzeSchemas(schemas, md);
- } catch (Exception e) {
- logger.debug("Exception analyzing schema, ignoring", e);
- }
-
- Collection<DbEntity> entities = dataNode.getEntityResolver().getDbEntities();
-
- boolean isIncluded = analyzer.compareTables(md, entities);
-
- if (isIncluded && analyzer.getErrorMessage() == null) {
- try {
- analyzer.compareColumns(md);
- } catch (SQLException e) {
- logger.debug("Exception analyzing schema, ignoring", e);
- }
- }
-
- processSchemaUpdate(dataNode, analyzer.getTableNoInDB(), analyzer.getErrorMessage(), entities.size());
- }
-
- protected void processSchemaUpdate(DataNode dataNode, List<String> mergerOnlyTable, String errorMessage,
- int entitiesSize) throws SQLException {
-
- if (mergerOnlyTable.size() == 0 && errorMessage == null) {
- logger.info("Full schema is present");
- } else {
- logger.info("Error - missing or partial schema detected");
- StringBuilder buffer = new StringBuilder("Schema mismatch detected");
-
- if (errorMessage != null) {
- buffer.append(": ").append(errorMessage);
- } else if (mergerOnlyTable.size() == entitiesSize) {
- buffer.append(": no schema found");
- } else {
- if (mergerOnlyTable.size() > 0) {
- buffer.append(": missing table '").append(mergerOnlyTable.get(0)).append('\'');
- }
- }
-
- throw new CayenneRuntimeException(buffer.toString());
- }
- }
+ private final static Log LOGGER = LogFactory.getLog(ThrowOnPartialSchemaStrategy.class);
+
+
+ @Override
+ protected void processSchemaUpdate(DataNode dataNode) throws SQLException {
+
+ SchemaAnalyzer analyzer = new SchemaAnalyzer();
+
+ List<String> schemas = new ArrayList<>();
+ DatabaseMetaData md = null;
+ try {
+
+ try (Connection connection = dataNode.getDataSource().getConnection();) {
+ md = connection.getMetaData();
+
+ try (ResultSet rs = md.getSchemas();) {
+ while (rs.next()) {
+ String schemaName = rs.getString(1);
+ schemas.add(schemaName);
+ }
+ }
+ }
+
+ analyzer.analyzeSchemas(schemas, md);
+ } catch (Exception e) {
+ LOGGER.debug("Exception analyzing schema, ignoring", e);
+ }
+
+ Collection<DbEntity> entities = dataNode.getEntityResolver().getDbEntities();
+
+ boolean isIncluded = analyzer.compareTables(md, entities);
+
+ if (isIncluded && analyzer.getErrorMessage() == null) {
+ try {
+ analyzer.compareColumns(md);
+ } catch (SQLException e) {
+ LOGGER.debug("Exception analyzing schema, ignoring", e);
+ }
+ }
+
+ processSchemaUpdate(dataNode, analyzer.getTableNoInDB(), analyzer.getErrorMessage(), entities.size());
+ }
+
+ protected void processSchemaUpdate(DataNode dataNode, List<String> mergerOnlyTable, String errorMessage, int entitiesSize)
+ throws SQLException {
+
+ if (mergerOnlyTable.size() == 0 && errorMessage == null) {
+ LOGGER.info("Full schema is present");
+ } else {
+ LOGGER.info("Error - missing or partial schema detected");
+ StringBuilder buffer = new StringBuilder("Schema mismatch detected");
+
+ if (errorMessage != null) {
+ buffer.append(": ").append(errorMessage);
+ } else if (mergerOnlyTable.size() == entitiesSize) {
+ buffer.append(": no schema found");
+ } else {
+ if (mergerOnlyTable.size() > 0) {
+ buffer.append(": missing table '").append(mergerOnlyTable.get(0)).append('\'');
+ }
+ }
+
+ throw new CayenneRuntimeException(buffer.toString());
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDataNodeFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDataNodeFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDataNodeFactory.java
index 07c7fdf..d419eb9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDataNodeFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDataNodeFactory.java
@@ -18,10 +18,8 @@
****************************************************************/
package org.apache.cayenne.configuration.server;
-import javax.sql.DataSource;
-
import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
+import org.apache.cayenne.access.dbsync.SchemaUpdateStrategyFactory;
import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
@@ -31,6 +29,8 @@ import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.log.JdbcEventLogger;
+import javax.sql.DataSource;
+
/**
* @since 4.0
*/
@@ -58,7 +58,7 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
protected AdhocObjectFactory objectFactory;
@Inject
- protected SchemaUpdateStrategy defaultSchemaUpdateStrategy;
+ protected SchemaUpdateStrategyFactory schemaUpdateStrategyFactory;
@Inject
protected SQLTemplateProcessor sqlTemplateProcessor;
@@ -81,20 +81,8 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
dataNode.setDataSourceFactory(nodeDescriptor.getDataSourceFactoryType());
dataNode.setDataSource(dataSource);
- // schema update strategy
- String schemaUpdateStrategyType = nodeDescriptor.getSchemaUpdateStrategyType();
-
- if (schemaUpdateStrategyType == null) {
- dataNode.setSchemaUpdateStrategy(defaultSchemaUpdateStrategy);
- dataNode.setSchemaUpdateStrategyName(defaultSchemaUpdateStrategy.getClass().getName());
- } else {
- SchemaUpdateStrategy strategy = objectFactory.newInstance(SchemaUpdateStrategy.class,
- schemaUpdateStrategyType);
- dataNode.setSchemaUpdateStrategyName(schemaUpdateStrategyType);
- dataNode.setSchemaUpdateStrategy(strategy);
- }
+ dataNode.setSchemaUpdateStrategy(schemaUpdateStrategyFactory.create(nodeDescriptor));
- // DbAdapter
dataNode.setAdapter(adapterFactory.createAdapter(nodeDescriptor, dataSource));
return dataNode;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
index 36516d9..286edce 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
@@ -22,9 +22,8 @@ import org.apache.cayenne.DataChannel;
import org.apache.cayenne.access.DataDomain;
import org.apache.cayenne.access.DefaultObjectMapRetainStrategy;
import org.apache.cayenne.access.ObjectMapRetainStrategy;
-import org.apache.cayenne.tx.TransactionFilter;
-import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
-import org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy;
+import org.apache.cayenne.access.dbsync.DefaultSchemaUpdateStrategyFactory;
+import org.apache.cayenne.access.dbsync.SchemaUpdateStrategyFactory;
import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
import org.apache.cayenne.access.jdbc.reader.DefaultRowReaderFactory;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
@@ -99,6 +98,7 @@ import org.apache.cayenne.resource.ResourceLocator;
import org.apache.cayenne.tx.DefaultTransactionFactory;
import org.apache.cayenne.tx.DefaultTransactionManager;
import org.apache.cayenne.tx.TransactionFactory;
+import org.apache.cayenne.tx.TransactionFilter;
import org.apache.cayenne.tx.TransactionManager;
import org.apache.cayenne.velocity.VelocitySQLTemplateProcessor;
@@ -207,10 +207,7 @@ public class ServerModule implements Module {
// call depending on DataNodeDescriptor data and the environment
binder.bind(DataSourceFactory.class).to(DelegatingDataSourceFactory.class);
- // a default SchemaUpdateStrategy (used when no explicit strategy is
- // specified in
- // XML)
- binder.bind(SchemaUpdateStrategy.class).to(SkipSchemaUpdateStrategy.class);
+ binder.bind(SchemaUpdateStrategyFactory.class).to(DefaultSchemaUpdateStrategyFactory.class);
// a default DBAdapterFactory used to load custom and automatic
// DbAdapters
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/test/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyBase.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyBase.java b/cayenne-server/src/test/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyBase.java
index 7c63192..3e35449 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyBase.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyBase.java
@@ -18,15 +18,6 @@
****************************************************************/
package org.apache.cayenne.access.dbsync;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.access.DataNode;
@@ -36,6 +27,15 @@ import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.unit.di.server.ServerCase;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
public class SchemaUpdateStrategyBase extends ServerCase {
@Inject
@@ -59,7 +59,6 @@ public class SchemaUpdateStrategyBase extends ServerCase {
}
protected void setStrategy(Class<? extends SchemaUpdateStrategy> type) throws Exception {
- node.setSchemaUpdateStrategyName(type.getName());
node.setSchemaUpdateStrategy(type.newInstance());
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/test/java/org/apache/cayenne/access/dbsync/TstSchemaUpdateStrategy.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/dbsync/TstSchemaUpdateStrategy.java b/cayenne-server/src/test/java/org/apache/cayenne/access/dbsync/TstSchemaUpdateStrategy.java
index 8e32500..a23cb8c 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/dbsync/TstSchemaUpdateStrategy.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/dbsync/TstSchemaUpdateStrategy.java
@@ -19,16 +19,10 @@
package org.apache.cayenne.access.dbsync;
import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
public class TstSchemaUpdateStrategy implements SchemaUpdateStrategy {
- public TstSchemaUpdateStrategy() {
- }
-
+ @Override
public void updateSchema(DataNode dataNode) {
}
-
- public void generateUpdateSchema(DataNode dataNode) {
- }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
index b0ba2b0..b8f4f7e 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
@@ -22,7 +22,8 @@ import org.apache.cayenne.ConfigurationException;
import org.apache.cayenne.DataChannel;
import org.apache.cayenne.access.DataDomain;
import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
+import org.apache.cayenne.access.dbsync.DefaultSchemaUpdateStrategyFactory;
+import org.apache.cayenne.access.dbsync.SchemaUpdateStrategyFactory;
import org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy;
import org.apache.cayenne.access.dbsync.ThrowOnPartialOrCreateSchemaStrategy;
import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
@@ -157,6 +158,7 @@ public class DataDomainProviderTest {
binder.bind(EventManager.class).toInstance(eventManager);
binder.bind(EntitySorter.class).toInstance(new AshwoodEntitySorter());
+ binder.bind(SchemaUpdateStrategyFactory.class).to(DefaultSchemaUpdateStrategyFactory.class);
final ResourceLocator locator = new ClassLoaderResourceLocator(classLoaderManager) {
@@ -179,7 +181,6 @@ public class DataDomainProviderTest {
binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
binder.bind(DataChannelDescriptorMerger.class).to(DefaultDataChannelDescriptorMerger.class);
binder.bind(DataChannelDescriptorLoader.class).toInstance(testLoader);
- binder.bind(SchemaUpdateStrategy.class).toInstance(new SkipSchemaUpdateStrategy());
binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
binder.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
@@ -221,7 +222,6 @@ public class DataDomainProviderTest {
assertNotNull(node1.getDataSource());
assertEquals(nodeDescriptor1.getParameters(), node1.getDataSourceLocation());
- assertEquals(nodeDescriptor1.getSchemaUpdateStrategyType(), node1.getSchemaUpdateStrategyName());
assertNotNull(node1.getSchemaUpdateStrategy());
assertEquals(nodeDescriptor1.getSchemaUpdateStrategyType(), node1.getSchemaUpdateStrategy().getClass()
.getName());
@@ -237,7 +237,6 @@ public class DataDomainProviderTest {
assertNull(node2.getDataSourceFactory());
assertNotNull(node2.getDataSource());
assertEquals(nodeDescriptor2.getParameters(), node2.getDataSourceLocation());
- assertEquals(SkipSchemaUpdateStrategy.class.getName(), node2.getSchemaUpdateStrategyName());
assertNotNull(node2.getSchemaUpdateStrategy());
assertEquals(SkipSchemaUpdateStrategy.class.getName(), node2.getSchemaUpdateStrategy().getClass().getName());
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index b8811de..de5376d 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -56,6 +56,7 @@ CAY-2108 cayenne-di: StackOverflow for decorator that takes Provider of the dele
CAY-2110 Obfuscated exception when processing iterated results
CAY-2119 ProjectUpgrader test failure (Windows)
CAY-2122 Vertical Inheritance: Cannot Insert Record For Implementing Class with Attribute And Relationship
+CAY-2125 SchemaUpdateStrategy doesn't work with multiple DataNodes
----------------------------------
Release: 4.0.M3
http://git-wip-us.apache.org/repos/asf/cayenne/blob/60fc4d26/docs/doc/src/main/resources/UPGRADE.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/UPGRADE.txt b/docs/doc/src/main/resources/UPGRADE.txt
index a99e083..50e3479 100644
--- a/docs/doc/src/main/resources/UPGRADE.txt
+++ b/docs/doc/src/main/resources/UPGRADE.txt
@@ -6,6 +6,10 @@ IMPORTANT: be sure to read all notes for the intermediate releases between your
-------------------------------------------------------------------------------
UPGRADING TO 4.0.M4
+* Per CAY-2125 we no longer inject SchemaUpdateStrategy directly. Instead SchemaUpgradeStrategyFactory is injected.
+ If you have your own modules with SchemaUpdateStrategy injection, it will be ignored. So please review your
+ DI code and update it to use SchemaUpgradeStrategyFactory (or likely its subclass).
+
* Per CAY-2060 4.0.M4 changes the way queries are stored in the mapping files, so all existing *.map.xml files should be upgraded.
To do that open each of your existing projects in the new CayenneModeler. Agree to perform an upgrade when asked.