Переглянути джерело

支持关系型DB连接配置默认主键

AE86 3 роки тому
батько
коміт
5dcd32c098

+ 2 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/AbstractDataBaseConfigChecker.java

@@ -19,6 +19,7 @@ public abstract class AbstractDataBaseConfigChecker implements ConnectorConfigCh
         String password = params.get("password");
         String url = params.get("url");
         String driverClassName = params.get("driverClassName");
+        String primaryKey = params.get("primaryKey");
         Assert.hasText(username, "Username is empty.");
         Assert.hasText(password, "Password is empty.");
         Assert.hasText(url, "Url is empty.");
@@ -28,6 +29,7 @@ public abstract class AbstractDataBaseConfigChecker implements ConnectorConfigCh
         connectorConfig.setPassword(password);
         connectorConfig.setUrl(url);
         connectorConfig.setDriverClassName(driverClassName);
+        connectorConfig.setPrimaryKey(primaryKey);
     }
 
     protected void modifyDql(DatabaseConfig connectorConfig, Map<String, String> params) {

+ 3 - 5
dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/CommandConfig.java

@@ -24,13 +24,11 @@ public class CommandConfig {
 
     private ConnectorConfig connectorConfig;
 
-    public CommandConfig(String type, Table table, Table originalTable) {
-        this.type = type;
-        this.table = table;
-        this.originalTable = originalTable;
+    public CommandConfig(String type, Table table, Table originalTable, ConnectorConfig connectorConfig) {
+        this(type, table, originalTable, connectorConfig, null);
     }
 
-    public CommandConfig(String type, Table table, Table originalTable, List<Filter> filter, ConnectorConfig connectorConfig) {
+    public CommandConfig(String type, Table table, Table originalTable, ConnectorConfig connectorConfig, List<Filter> filter) {
         this.type = type;
         this.table = table;
         this.originalTable = originalTable;

+ 1 - 7
dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/SqlBuilderConfig.java

@@ -19,13 +19,7 @@ public class SqlBuilderConfig {
     // 引号
     private String quotation;
 
-    public SqlBuilderConfig(String name, String pk) {
-        this.tableName = name;
-        this.pk = pk;
-    }
-
-    public SqlBuilderConfig(Database database, String tableName, String pk, List<Field> fields, String queryFilter,
-                            String quotation) {
+    public SqlBuilderConfig(Database database, String tableName, String pk, List<Field> fields, String queryFilter, String quotation) {
         this.database = database;
         this.tableName = tableName;
         this.pk = pk;

+ 20 - 23
dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/AbstractDatabaseConnector.java

@@ -12,7 +12,6 @@ import org.dbsyncer.connector.constant.ConnectorConstant;
 import org.dbsyncer.connector.enums.OperationEnum;
 import org.dbsyncer.connector.enums.SetterEnum;
 import org.dbsyncer.connector.enums.SqlBuilderEnum;
-import org.dbsyncer.connector.enums.TableTypeEnum;
 import org.dbsyncer.connector.model.Field;
 import org.dbsyncer.connector.model.Filter;
 import org.dbsyncer.connector.model.MetaInfo;
@@ -175,20 +174,17 @@ public abstract class AbstractDatabaseConnector extends AbstractConnector
         Map<String, String> map = new HashMap<>();
 
         String query = ConnectorConstant.OPERTION_QUERY;
-        map.put(query, buildSql(query, table, commandConfig.getOriginalTable(), queryFilterSql));
+        map.put(query, buildSql(query, commandConfig, queryFilterSql));
 
         // 获取查询总数SQL
         String quotation = buildSqlWithQuotation();
-        String pk = findTablePrimaryKey(commandConfig.getOriginalTable(), quotation);
+        String pk = findOriginalTablePrimaryKey(commandConfig, quotation);
         StringBuilder queryCount = new StringBuilder();
         queryCount.append("SELECT COUNT(1) FROM (SELECT 1 FROM ").append(quotation).append(table.getName()).append(quotation);
         if (StringUtil.isNotBlank(queryFilterSql)) {
             queryCount.append(queryFilterSql);
         }
-        if (!StringUtil.isBlank(pk)) {
-            queryCount.append(" GROUP BY ").append(pk);
-        }
-        queryCount.append(") DBSYNCER_T");
+        queryCount.append(" GROUP BY ").append(pk).append(") DBSYNCER_T");
         map.put(ConnectorConstant.OPERTION_QUERY_COUNT, queryCount.toString());
         return map;
     }
@@ -197,22 +193,19 @@ public abstract class AbstractDatabaseConnector extends AbstractConnector
     public Map<String, String> getTargetCommand(CommandConfig commandConfig) {
         // 获取增删改SQL
         Map<String, String> map = new HashMap<>();
-        Table table = commandConfig.getTable();
-        Table originalTable = commandConfig.getOriginalTable();
-
         String insert = SqlBuilderEnum.INSERT.getName();
-        map.put(insert, buildSql(insert, table, originalTable, null));
+        map.put(insert, buildSql(insert, commandConfig, null));
 
         String update = SqlBuilderEnum.UPDATE.getName();
-        map.put(update, buildSql(update, table, originalTable, null));
+        map.put(update, buildSql(update, commandConfig, null));
 
         String delete = SqlBuilderEnum.DELETE.getName();
-        map.put(delete, buildSql(delete, table, originalTable, null));
+        map.put(delete, buildSql(delete, commandConfig, null));
 
         // 获取查询数据行是否存在
         String quotation = buildSqlWithQuotation();
-        String pk = findTablePrimaryKey(commandConfig.getOriginalTable(), quotation);
-        StringBuilder queryCount = new StringBuilder().append("SELECT COUNT(1) FROM ").append(quotation).append(table.getName()).append(
+        String pk = findOriginalTablePrimaryKey(commandConfig, quotation);
+        StringBuilder queryCount = new StringBuilder().append("SELECT COUNT(1) FROM ").append(quotation).append(commandConfig.getTable().getName()).append(
                 quotation).append(" WHERE ").append(pk).append(" = ?");
         String queryCountExist = ConnectorConstant.OPERTION_QUERY_COUNT_EXIST;
         map.put(queryCountExist, queryCount.toString());
@@ -323,12 +316,12 @@ public abstract class AbstractDatabaseConnector extends AbstractConnector
      * 获取查询SQL
      *
      * @param type           {@link SqlBuilderEnum}
-     * @param table
-     * @param originalTable
+     * @param commandConfig
      * @param queryFilterSQL
      * @return
      */
-    protected String buildSql(String type, Table table, Table originalTable, String queryFilterSQL) {
+    protected String buildSql(String type, CommandConfig commandConfig, String queryFilterSQL) {
+        Table table = commandConfig.getTable();
         if (null == table) {
             logger.error("Table can not be null.");
             throw new ConnectorException("Table can not be null.");
@@ -364,7 +357,7 @@ public abstract class AbstractDatabaseConnector extends AbstractConnector
             throw new ConnectorException("Table name can not be empty.");
         }
         if (StringUtil.isBlank(pk)) {
-            pk = findTablePrimaryKey(originalTable, "");
+            pk = findOriginalTablePrimaryKey(commandConfig, "");
         }
 
         SqlBuilderConfig config = new SqlBuilderConfig(this, tableName, pk, fields, queryFilterSQL, buildSqlWithQuotation());
@@ -420,11 +413,12 @@ public abstract class AbstractDatabaseConnector extends AbstractConnector
     /**
      * 返回主键名称
      *
-     * @param table
+     * @param commandConfig
      * @param quotation
      * @return
      */
-    protected String findTablePrimaryKey(Table table, String quotation) {
+    protected String findOriginalTablePrimaryKey(CommandConfig commandConfig, String quotation) {
+        Table table = commandConfig.getOriginalTable();
         if (null != table) {
             List<Field> column = table.getColumn();
             if (!CollectionUtils.isEmpty(column)) {
@@ -435,10 +429,13 @@ public abstract class AbstractDatabaseConnector extends AbstractConnector
                 }
             }
         }
-        if (!TableTypeEnum.isView(table.getType())) {
+
+        DatabaseConfig cfg = (DatabaseConfig) commandConfig.getConnectorConfig();
+        if (StringUtil.isBlank(cfg.getPrimaryKey())) {
             throw new ConnectorException("Table primary key can not be empty.");
         }
-        return "";
+
+        return new StringBuilder(quotation).append(cfg.getPrimaryKey()).append(quotation).toString();
     }
 
     /**

+ 1 - 7
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/DQLSqlServerConnector.java

@@ -1,9 +1,7 @@
 package org.dbsyncer.connector.sql;
 
-import org.dbsyncer.common.util.StringUtil;
-import org.dbsyncer.connector.ConnectorException;
-import org.dbsyncer.connector.model.PageSql;
 import org.dbsyncer.connector.constant.DatabaseConstant;
+import org.dbsyncer.connector.model.PageSql;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -13,10 +11,6 @@ public final class DQLSqlServerConnector extends AbstractDQLConnector {
 
     @Override
     public String getPageSql(PageSql config) {
-        if (StringUtil.isBlank(config.getPk())) {
-            logger.error("Table primary key can not be empty.");
-            throw new ConnectorException("Table primary key can not be empty.");
-        }
         return String.format(DatabaseConstant.SQLSERVER_PAGE_SQL, config.getPk(), config.getQuerySql());
     }
 

+ 3 - 8
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sqlserver/SqlServerConnector.java

@@ -1,15 +1,14 @@
 package org.dbsyncer.connector.sqlserver;
 
 import org.dbsyncer.common.util.StringUtil;
-import org.dbsyncer.connector.ConnectorException;
 import org.dbsyncer.connector.config.CommandConfig;
 import org.dbsyncer.connector.config.DatabaseConfig;
-import org.dbsyncer.connector.model.PageSql;
-import org.dbsyncer.connector.model.Table;
 import org.dbsyncer.connector.constant.ConnectorConstant;
 import org.dbsyncer.connector.constant.DatabaseConstant;
 import org.dbsyncer.connector.database.AbstractDatabaseConnector;
 import org.dbsyncer.connector.database.DatabaseConnectorMapper;
+import org.dbsyncer.connector.model.PageSql;
+import org.dbsyncer.connector.model.Table;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -29,10 +28,6 @@ public final class SqlServerConnector extends AbstractDatabaseConnector {
 
     @Override
     public String getPageSql(PageSql config) {
-        if (StringUtil.isBlank(config.getPk())) {
-            logger.error("Table primary key can not be empty.");
-            throw new ConnectorException("Table primary key can not be empty.");
-        }
         return String.format(DatabaseConstant.SQLSERVER_PAGE_SQL, config.getPk(), config.getQuerySql());
     }
 
@@ -51,7 +46,7 @@ public final class SqlServerConnector extends AbstractDatabaseConnector {
         Map<String, String> map = new HashMap<>();
 
         String query = ConnectorConstant.OPERTION_QUERY;
-        map.put(query, this.buildSql(query, table, commandConfig.getOriginalTable(), queryFilterSql));
+        map.put(query, this.buildSql(query, commandConfig, queryFilterSql));
 
         // 获取查询总数SQL
         StringBuilder queryCount = new StringBuilder();

+ 4 - 5
dbsyncer-parser/src/main/java/org/dbsyncer/parser/ParserFactory.java

@@ -139,9 +139,8 @@ public class ParserFactory implements Parser {
 
     @Override
     public Map<String, String> getCommand(Mapping mapping, TableGroup tableGroup) {
-        ConnectorConfig connectorConfig = getConnectorConfig(mapping.getSourceConnectorId());
-        String sType = connectorConfig.getConnectorType();
-        String tType = getConnectorConfig(mapping.getTargetConnectorId()).getConnectorType();
+        ConnectorConfig sConnConfig = getConnectorConfig(mapping.getSourceConnectorId());
+        ConnectorConfig tConnConfig = getConnectorConfig(mapping.getTargetConnectorId());
         Table sourceTable = tableGroup.getSourceTable();
         Table targetTable = tableGroup.getTargetTable();
         Table sTable = new Table(sourceTable.getName(), sourceTable.getType(), new ArrayList<>());
@@ -157,8 +156,8 @@ public class ParserFactory implements Parser {
                 }
             });
         }
-        final CommandConfig sourceConfig = new CommandConfig(sType, sTable, sourceTable, tableGroup.getFilter(), connectorConfig);
-        final CommandConfig targetConfig = new CommandConfig(tType, tTable, targetTable);
+        final CommandConfig sourceConfig = new CommandConfig(sConnConfig.getConnectorType(), sTable, sourceTable, sConnConfig, tableGroup.getFilter());
+        final CommandConfig targetConfig = new CommandConfig(tConnConfig.getConnectorType(), tTable, targetTable, tConnConfig);
         // 获取连接器同步参数
         Map<String, String> command = connectorFactory.getCommand(sourceConfig, targetConfig);
         return command;

+ 21 - 4
dbsyncer-web/src/main/resources/public/connector/addMysql.html

@@ -10,21 +10,38 @@
         </div>
         <label class="col-sm-2 control-label">密码 <strong class="driverVerifcateRequired">*</strong></label>
         <div class="col-sm-4 ">
-            <input class="form-control" name="password" type="password" maxlength="32" dbsyncer-valid="require" th:value="${connector?.config?.password}"/>
+            <input class="form-control" name="password" type="password" maxlength="32" dbsyncer-valid="require"
+                   th:value="${connector?.config?.password}"/>
         </div>
     </div>
     <div class="form-group">
         <label class="col-sm-2 control-label">URL <strong class="driverVerifcateRequired">*</strong></label>
         <div class="col-sm-10">
-            <textarea name="url" class="form-control dbsyncer_textarea_resize_none" maxlength="1024" dbsyncer-valid="require" rows="5" th:text="${connector?.config?.url} ?: 'jdbc:mysql://127.0.0.1:3306/test?rewriteBatchedStatements=true&useUnicode=true&amp;characterEncoding=UTF8&amp;serverTimezone=Asia/Shanghai&amp;useSSL=false&amp;verifyServerCertificate=false&amp;autoReconnect=true&amp;failOverReadOnly=false'"></textarea>
+            <textarea name="url" class="form-control dbsyncer_textarea_resize_none" maxlength="1024"
+                      dbsyncer-valid="require" rows="5"
+                      th:text="${connector?.config?.url} ?: 'jdbc:mysql://127.0.0.1:3306/test?rewriteBatchedStatements=true&useUnicode=true&amp;characterEncoding=UTF8&amp;serverTimezone=Asia/Shanghai&amp;useSSL=false&amp;verifyServerCertificate=false&amp;autoReconnect=true&amp;failOverReadOnly=false'"></textarea>
         </div>
     </div>
+    <div class="form-group">
+        <label class="col-sm-2 control-label">主键</label>
+        <div class="col-sm-4">
+            <input class="form-control" name="primaryKey" type="text" maxlength="32" dbsyncer-valid="require"
+                   placeholder="ID" th:value="${connector?.config?.primaryKey}"/>
+        </div>
+        <div class="col-sm-6"></div>
+    </div>
     <div class="form-group">
         <label class="col-sm-2 control-label">驱动 </label>
         <div class="col-sm-10">
             <select class="form-control select-control" name="driverClassName">
-                <option value="com.mysql.jdbc.Driver" th:selected="${connector?.config?.driverClassName eq 'com.mysql.jdbc.Driver'}">com.mysql.jdbc.Driver</option>
-                <option value="com.mysql.cj.jdbc.Driver" th:selected="${connector?.config?.driverClassName eq 'com.mysql.cj.jdbc.Driver'}">com.mysql.cj.jdbc.Driver</option>
+                <option value="com.mysql.jdbc.Driver"
+                        th:selected="${connector?.config?.driverClassName eq 'com.mysql.jdbc.Driver'}">
+                    com.mysql.jdbc.Driver
+                </option>
+                <option value="com.mysql.cj.jdbc.Driver"
+                        th:selected="${connector?.config?.driverClassName eq 'com.mysql.cj.jdbc.Driver'}">
+                    com.mysql.cj.jdbc.Driver
+                </option>
             </select>
         </div>
     </div>

+ 15 - 3
dbsyncer-web/src/main/resources/public/connector/addOracle.html

@@ -10,19 +10,31 @@
         </div>
         <label class="col-sm-2 control-label">密码 <strong class="driverVerifcateRequired">*</strong></label>
         <div class="col-sm-4 ">
-            <input class="form-control" name="password" type="password" maxlength="32" dbsyncer-valid="require" th:value="${connector?.config?.password}"/>
+            <input class="form-control" name="password" type="password" maxlength="32" dbsyncer-valid="require"
+                   th:value="${connector?.config?.password}"/>
         </div>
     </div>
     <div class="form-group">
         <label class="col-sm-2 control-label">URL <strong class="driverVerifcateRequired">*</strong></label>
         <div class="col-sm-10">
-            <textarea name="url" class="form-control dbsyncer_textarea_resize_none" maxlength="1024" dbsyncer-valid="require" rows="5" th:text="${connector?.config?.url} ?: 'jdbc:oracle:thin:@127.0.0.1:1521:ORCL'"></textarea>
+            <textarea name="url" class="form-control dbsyncer_textarea_resize_none" maxlength="1024"
+                      dbsyncer-valid="require" rows="5"
+                      th:text="${connector?.config?.url} ?: 'jdbc:oracle:thin:@127.0.0.1:1521:ORCL'"></textarea>
         </div>
     </div>
+    <div class="form-group">
+        <label class="col-sm-2 control-label">主键</label>
+        <div class="col-sm-4">
+            <input class="form-control" name="primaryKey" type="text" maxlength="32" dbsyncer-valid="require"
+                   placeholder="ID" th:value="${connector?.config?.primaryKey}"/>
+        </div>
+        <div class="col-sm-6"></div>
+    </div>
     <div class="form-group">
         <label class="col-sm-2 control-label">驱动 </label>
         <div class="col-sm-10">
-            <input class="form-control" readonly="true" name="driverClassName" type="text" th:value="${connector?.config?.driverClassName} ?: 'oracle.jdbc.OracleDriver'" />
+            <input class="form-control" readonly="true" name="driverClassName" type="text"
+                   th:value="${connector?.config?.driverClassName} ?: 'oracle.jdbc.OracleDriver'"/>
         </div>
     </div>
 </div>

+ 5 - 1
dbsyncer-web/src/main/resources/public/connector/addPostgreSQL.html

@@ -29,7 +29,11 @@
             <input class="form-control" dbsyncer-valid="require" maxlength="32" name="schema" placeholder="public"
                    th:value="${connector?.config?.schema} ?: 'public'" type="text"/>
         </div>
-        <div class="col-sm-6"></div>
+        <label class="col-sm-2 control-label">主键</label>
+        <div class="col-sm-4">
+            <input class="form-control" name="primaryKey" type="text" maxlength="32" dbsyncer-valid="require"
+                   placeholder="ID" th:value="${connector?.config?.primaryKey}"/>
+        </div>
     </div>
     <div class="form-group">
         <label class="col-sm-2 control-label">删除Slot <i aria-hidden="true" class="fa fa-question-circle fa_gray" title="增量同步,停止驱动自动删除Slot"></i></label>

+ 7 - 2
dbsyncer-web/src/main/resources/public/connector/addSqlServer.html

@@ -22,9 +22,14 @@
     <div class="form-group">
         <label class="col-sm-2 control-label">架构名 <strong class="driverVerifcateRequired">*</strong></label>
         <div class="col-sm-4">
-            <input class="form-control" name="schema" type="text" maxlength="32" dbsyncer-valid="require" placeholder="dbo" th:value="${connector?.config?.schema} ?: 'dbo'"/>
+            <input class="form-control" name="schema" type="text" maxlength="32" dbsyncer-valid="require"
+                   placeholder="dbo" th:value="${connector?.config?.schema} ?: 'dbo'"/>
+        </div>
+        <label class="col-sm-2 control-label">主键</label>
+        <div class="col-sm-4">
+            <input class="form-control" name="primaryKey" type="text" maxlength="32" dbsyncer-valid="require"
+                   placeholder="ID" th:value="${connector?.config?.primaryKey}"/>
         </div>
-        <div class="col-sm-6"></div>
     </div>
     <div class="form-group">
         <label class="col-sm-2 control-label">驱动 </label>