Explorar o código

Merge remote-tracking branch 'remotes/origin/master' into v_2.0

# Conflicts:
#	dbsyncer-biz/pom.xml
#	dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/MappingServiceImpl.java
#	dbsyncer-cache/pom.xml
#	dbsyncer-cluster/pom.xml
#	dbsyncer-common/pom.xml
#	dbsyncer-connector/dbsyncer-connector-file/pom.xml
#	dbsyncer-connector/dbsyncer-connector-file/src/main/java/org/dbsyncer/connector/file/model/FileBitValueMapper.java
#	dbsyncer-connector/pom.xml
#	dbsyncer-manager/pom.xml
#	dbsyncer-monitor/pom.xml
#	dbsyncer-parser/pom.xml
#	dbsyncer-plugin/pom.xml
#	dbsyncer-sdk/src/main/java/org/dbsyncer/sdk/connector/database/ds/SimpleDataSource.java
#	dbsyncer-storage/pom.xml
#	dbsyncer-web/pom.xml
#	pom.xml
AE86 hai 1 ano
pai
achega
d5f88342ad

+ 4 - 7
README.md

@@ -30,6 +30,9 @@
 | SQL | ✔ |  | 支持以上关系型数据库 |
 | 后期计划 | Redis | | |
 
+## 📚使用手册
+### [Wiki](https://gitee.com/ghi/dbsyncer/wikis "https://gitee.com/ghi/dbsyncer/wikis")
+
 ## ✨预览
 ### 驱动管理
 ![连接器和驱动](https://images.gitee.com/uploads/images/2021/0903/003755_01016fc1_376718.png "驱动管理.png")
@@ -37,8 +40,6 @@
 ### 监控
 ![监控](https://foruda.gitee.com/images/1694424923138969858/111e55e0_376718.png "监控")
 
-
-
 ## 📦安装配置
 #### 步骤
 1. 安装[JDK 1.8](https://www.oracle.com/java/technologies/jdk8-downloads.html)(省略详细)
@@ -68,12 +69,8 @@ $ ./build.sh
 * 同步数据乱码。案例:[mysql8表导入sqlserver2008R2后,sqlserver表nvarchar字段内容为乱码](https://gitee.com/ghi/dbsyncer/issues/I4JXY0) 
 * [如何开启远程debug模式?](https://gitee.com/ghi/dbsyncer/issues/I63F6R)  
 
-## 💕了解更多
-* QQ群: 875519623或点击右侧按钮<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=fce8d51b264130bac5890674e7db99f82f7f8af3f790d49fcf21eaafc8775f2a"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="数据同步dbsyncer" title="数据同步dbsyncer" /></a>
-* [使用文档](https://gitee.com/ghi/dbsyncer/wikis "https://gitee.com/ghi/dbsyncer/wikis")
-* [博客地址](https://my.oschina.net/dbsyncer "https://my.oschina.net/dbsyncer")(小提示:现在需要先登录,才能查看完整的教程信息,包含截图等😂)
-
 ## 🤝贡献支持
+* QQ群: 875519623或点击右侧按钮<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=fce8d51b264130bac5890674e7db99f82f7f8af3f790d49fcf21eaafc8775f2a"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="数据同步dbsyncer" title="数据同步dbsyncer" /></a>
 * 如有比较着急的需求或建议(想支持某版本的中间件,最好能描述清楚你的原始需求,作者会帮你提供一些建议方案),欢迎大家[【新建issuses】](https://gitee.com/ghi/dbsyncer/issues/new?issue%5Bassignee_id%5D=0&issue%5Bmilestone_id%5D=0)!
 * DBSyncer研发团队目标:**取之社区,用于社区**。为了能让项目得到可持续发展,我们期望获得更多的支持者! 
 1.  **内推项目** 如您觉得项目不错,可推荐到公司,建立长期稳定的商业合作,提供更专业的技术服务。(入群联系群主)

+ 8 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/MappingService.java

@@ -1,6 +1,7 @@
 package org.dbsyncer.biz;
 
 import org.dbsyncer.biz.vo.MappingVo;
+import org.dbsyncer.parser.model.Connector;
 
 import java.util.List;
 import java.util.Map;
@@ -69,4 +70,11 @@ public interface MappingService {
      */
     String stop(String id);
 
+    /**
+     * 刷新表
+     *
+     * @param connector
+     */
+    void refreshTables(Connector connector);
+
 }

+ 11 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/MappingServiceImpl.java

@@ -9,6 +9,8 @@ import org.dbsyncer.biz.checker.impl.mapping.MappingChecker;
 import org.dbsyncer.biz.vo.ConnectorVo;
 import org.dbsyncer.biz.vo.MappingVo;
 import org.dbsyncer.biz.vo.MetaVo;
+import org.dbsyncer.common.snowflake.SnowflakeIdWorker;
+import org.dbsyncer.common.spi.ConnectorMapper;
 import org.dbsyncer.common.util.CollectionUtils;
 import org.dbsyncer.common.util.JsonUtil;
 import org.dbsyncer.common.util.StringUtil;
@@ -284,4 +286,13 @@ public class MappingServiceImpl extends BaseServiceImpl implements MappingServic
         }
     }
 
+    @Override
+    public void refreshTables(Connector connector) {
+        // 刷新数据表
+        ConnectorMapper connectorMapper = manager.connect(connector.getConfig());
+        List<Table> table = manager.getTable(connectorMapper);
+        connector.setTable(table);
+        manager.editConfigModel(connector);
+    }
+
 }

+ 0 - 0
dbsyncer-cache/pom.xml


+ 5 - 0
dbsyncer-connector/dbsyncer-connector-file/src/main/java/org/dbsyncer/connector/file/FileConnector.java

@@ -36,6 +36,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.sql.Types;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -60,6 +61,10 @@ public final class FileConnector extends AbstractConnector implements ConnectorS
     private final FileResolver fileResolver = new FileResolver();
     private final FileConfigValidator configValidator = new FileConfigValidator();
 
+    public FileConnector() {
+        VALUE_MAPPERS.put(Types.BIT, new FileBitValueMapper());
+    }
+
     @Override
     public String getConnectorType() {
         return TYPE;

+ 0 - 0
dbsyncer-connector/dbsyncer-connector-file/src/main/java/org/dbsyncer/connector/file/model/FileBitValueMapper.java


+ 0 - 0
dbsyncer-monitor/pom.xml


+ 59 - 15
dbsyncer-sdk/src/main/java/org/dbsyncer/sdk/connector/database/ds/SimpleDataSource.java

@@ -12,11 +12,31 @@ import java.sql.SQLFeatureNotSupportedException;
 import java.time.Instant;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Logger;
 
 public class SimpleDataSource implements DataSource, AutoCloseable {
 
-    private final BlockingQueue<SimpleConnection> pool = new LinkedBlockingQueue<>(300);
+    /**
+     * 默认最大连接
+     */
+    private final int MAX_IDLE = 300;
+
+    /**
+     * 连接上限后最大等待时间(秒)
+     */
+    private final int MAX_WAIT_SECONDS = 3;
+
+    /**
+     * 活跃连接数
+     */
+    private AtomicInteger activeNum = new AtomicInteger(0);
+
+    private final ReentrantLock lock = new ReentrantLock();
+
+    private final BlockingQueue<SimpleConnection> pool = new LinkedBlockingQueue<>(MAX_IDLE);
     /**
      * 有效期(毫秒),默认60s
      */
@@ -39,21 +59,35 @@ public class SimpleDataSource implements DataSource, AutoCloseable {
 
     @Override
     public Connection getConnection() throws SQLException {
-        SimpleConnection poll = pool.poll();
-        if (null == poll) {
-            return createConnection();
-        }
-
-        // 连接无效
-        if (!poll.isValid(VALID_TIMEOUT_SECONDS)) {
-            return createConnection();
-        }
+        try {
+            lock.lock();
+            //如果当前连接数大于或等于最大连接数
+            if (activeNum.get() >= MAX_IDLE) {
+                //等待3秒
+                TimeUnit.SECONDS.sleep(MAX_WAIT_SECONDS);
+                if (activeNum.get() >= MAX_IDLE) {
+                    throw new ConnectorException(String.format("数据库连接数超过上限%d,url=%s", MAX_IDLE, url));
+                }
+            }
+            SimpleConnection poll = pool.poll();
+            if (null == poll) {
+                return createConnection();
+            }
+            // 连接无效
+            if (!poll.isValid(VALID_TIMEOUT_SECONDS)) {
+                return createConnection();
+            }
 
-        // 连接过期
-        if (isExpired(poll)) {
-            return createConnection();
+            // 连接过期
+            if (isExpired(poll)) {
+                return createConnection();
+            }
+            return poll;
+        } catch (InterruptedException e) {
+            throw new ConnectorException(e);
+        } finally {
+            lock.unlock();
         }
-        return poll;
     }
 
     @Override
@@ -103,6 +137,9 @@ public class SimpleDataSource implements DataSource, AutoCloseable {
 
     public void close(Connection connection) {
         if (connection != null && connection instanceof SimpleConnection) {
+
+            activeNum.decrementAndGet();
+
             SimpleConnection simpleConnection = (SimpleConnection) connection;
             // 连接过期
             if (isExpired(simpleConnection)) {
@@ -132,7 +169,14 @@ public class SimpleDataSource implements DataSource, AutoCloseable {
      * @throws SQLException
      */
     private SimpleConnection createConnection() throws SQLException {
-        return new SimpleConnection(DatabaseUtil.getConnection(driverClassName, url, username, password), StringUtil.equals(driverClassName, "oracle.jdbc.OracleDriver"));
+        SimpleConnection simpleConnection = null;
+        try {
+            simpleConnection = new SimpleConnection(DatabaseUtil.getConnection(driverClassName, url, username, password), StringUtil.equals(driverClassName, "oracle.jdbc.OracleDriver"));
+            activeNum.incrementAndGet();
+        } catch (SQLException e) {
+            throw new ConnectorException(e);
+        }
+        return simpleConnection;
     }
 
 }

+ 15 - 0
dbsyncer-web/src/main/java/org/dbsyncer/web/controller/index/MappingController.java

@@ -3,6 +3,7 @@ package org.dbsyncer.web.controller.index;
 import org.dbsyncer.biz.ConnectorService;
 import org.dbsyncer.biz.MappingService;
 import org.dbsyncer.biz.TableGroupService;
+import org.dbsyncer.biz.vo.MappingVo;
 import org.dbsyncer.biz.vo.RestResult;
 import org.dbsyncer.web.controller.BaseController;
 import org.slf4j.Logger;
@@ -139,4 +140,18 @@ public class MappingController extends BaseController {
         }
     }
 
+    @PostMapping(value = "/refreshTables")
+    @ResponseBody
+    public RestResult refreshTables(@RequestParam(value = "id") String id) {
+        try {
+            MappingVo mapping = mappingService.getMapping(id);
+            mappingService.refreshTables(mapping.getSourceConnector());
+            mappingService.refreshTables(mapping.getTargetConnector());
+            return RestResult.restSuccess(id);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            return RestResult.restFail(e.getMessage());
+        }
+    }
+
 }

+ 6 - 1
dbsyncer-web/src/main/resources/public/mapping/editTable.html

@@ -56,7 +56,12 @@
 
     <div class="form-group">
         <div class="row">
-            <div class="col-md-10"></div>
+            <div class="col-md-2">&nbsp;
+                <button id="refreshTableBtn" type="button" class="btn btn-default" th:title="刷新数据表" th:tableGroupId="${mapping?.id}">
+                    <span class="fa fa-refresh"></span>刷新数据表
+                </button>
+            </div>
+            <div class="col-md-8"></div>
             <div class="col-md-2 text-right">
                 <button id="tableGroupDelBtn" th:mappingId="${mapping?.id}" type="button" class="btn btn-default" disabled="disabled">
                     <span class="fa fa-remove"></span>删除

+ 18 - 0
dbsyncer-web/src/main/resources/static/js/mapping/edit.js

@@ -201,6 +201,22 @@ function mappingModifyName(){
     });
 }
 
+// 绑定刷新表字段事件
+function bindRefreshTablesClick() {
+    let $refreshBtn = $("#refreshTableBtn");
+    $refreshBtn.bind('click', function(){
+        let id = $(this).attr("tableGroupId");
+        doPoster("/mapping/refreshTables", {'id': id}, function (data) {
+            if (data.success == true) {
+                bootGrowl("刷新数据表成功!", "success");
+                doLoader('/mapping/page/edit?id=' + id);
+            } else {
+                bootGrowl(data.resultValue, "danger");
+            }
+        });
+    });
+}
+
 $(function () {
     // 绑定同步方式切换事件
     bindMappingModelChange();
@@ -215,6 +231,8 @@ $(function () {
     initMultipleInputTags();
     // 绑定删除表关系点击事件
     bindMappingTableGroupDelClick();
+    //绑定刷新数据表按钮点击事件
+    bindRefreshTablesClick();
 
     // 初始化select插件
     initSelectIndex($(".select-control-table"), -1);