Parcourir la source

增加数据库维护基础功能->执行sql

zhouhao il y a 7 ans
Parent
commit
6be0b442e5
17 fichiers modifiés avec 873 ajouts et 1 suppressions
  1. 22 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/pom.xml
  2. 47 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/DatabaseManagerService.java
  3. 19 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/SqlExecuteRequest.java
  4. 29 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/SqlExecuteResult.java
  5. 30 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/SqlInfo.java
  6. 37 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/meta/ObjectMetadata.java
  7. 84 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/meta/table/ColumnMetadata.java
  8. 44 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/meta/table/Constraint.java
  9. 28 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/meta/table/ForeignConstraint.java
  10. 32 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/meta/table/TableMetadata.java
  11. 39 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/pom.xml
  12. 245 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/src/main/java/org/hswebframework/web/datasource/manager/simple/DefaultLocalTransactionExecutor.java
  13. 100 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/src/main/java/org/hswebframework/web/datasource/manager/simple/SimpleDatabaseManagerService.java
  14. 24 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/src/main/java/org/hswebframework/web/datasource/manager/simple/TransactionExecutor.java
  15. 71 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/src/test/java/org/hswebframework/web/datasource/manager/simple/SimpleDatabaseManagerServiceTest.java
  16. 16 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/src/test/resources/application.yml
  17. 6 1
      hsweb-system/hsweb-system-database-manager/pom.xml

+ 22 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/pom.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-system-database-manager</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-system-database-manager-api</artifactId>
+    <description>数据库维护接口</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-datasource-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>

+ 47 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/DatabaseManagerService.java

@@ -0,0 +1,47 @@
+package org.hswebframework.web.database.manager;
+
+import org.hswebframework.web.database.manager.meta.ObjectMetadata;
+import org.hswebframework.web.datasource.DynamicDataSource;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author zhouhao
+ */
+public interface DatabaseManagerService {
+
+    /**
+     * 开启一个指定数据源的事务,并返回事务ID,在其他操作的时候,使用事务ID共享同一个事务
+     *
+     * @param datasourceId 数据源ID {@link DynamicDataSource#getId()}
+     * @return 事务ID
+     */
+    String newTransaction(String datasourceId);
+
+    /**
+     * 对默认数据源开启事务,并返回事务ID,在其他操作的时候,使用事务ID共享同一个事务
+     *
+     * @return 事务ID
+     */
+    String newTransaction();
+
+    /**
+     * 提交事务
+     *
+     * @param transactionId 事务ID
+     */
+    void commit(String transactionId);
+
+    /**
+     * 回滚事务
+     *
+     * @param transactionId 事务ID
+     */
+    void rollback(String transactionId);
+
+    List<SqlExecuteResult> execute(String transactionId, SqlExecuteRequest request);
+
+    Map<ObjectMetadata.ObjectType, List<ObjectMetadata>> getMetas(String datasourceId);
+
+}

+ 19 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/SqlExecuteRequest.java

@@ -0,0 +1,19 @@
+package org.hswebframework.web.database.manager;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author zhouhao
+ */
+public class SqlExecuteRequest implements Serializable{
+    private List<SqlInfo> sql;
+
+    public List<SqlInfo> getSql() {
+        return sql;
+    }
+
+    public void setSql(List<SqlInfo> sql) {
+        this.sql = sql;
+    }
+}

+ 29 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/SqlExecuteResult.java

@@ -0,0 +1,29 @@
+package org.hswebframework.web.database.manager;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class SqlExecuteResult {
+
+    private SqlInfo sqlInfo;
+
+    private Object result;
+
+    public SqlInfo getSqlInfo() {
+        return sqlInfo;
+    }
+
+    public void setSqlInfo(SqlInfo sqlInfo) {
+        this.sqlInfo = sqlInfo;
+    }
+
+    public Object getResult() {
+        return result;
+    }
+
+    public void setResult(Object result) {
+        this.result = result;
+    }
+}

+ 30 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/SqlInfo.java

@@ -0,0 +1,30 @@
+package org.hswebframework.web.database.manager;
+
+import java.io.Serializable;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class SqlInfo implements Serializable {
+    private String sql;
+
+    private String type;
+
+    public String getSql() {
+        return sql;
+    }
+
+    public void setSql(String sql) {
+        this.sql = sql;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+}

+ 37 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/meta/ObjectMetadata.java

@@ -0,0 +1,37 @@
+package org.hswebframework.web.database.manager.meta;
+
+import java.io.Serializable;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public abstract class ObjectMetadata implements Serializable {
+
+    protected String name;
+
+    protected ObjectType type;
+
+    public ObjectType getType() {
+        return type;
+    }
+
+    public void setType(ObjectType type) {
+        this.type = type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public enum ObjectType {
+        TABLE,//表
+        VIEW,//视图
+        SEQUENCES//序列
+    }
+}

+ 84 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/meta/table/ColumnMetadata.java

@@ -0,0 +1,84 @@
+package org.hswebframework.web.database.manager.meta.table;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class ColumnMetadata implements Serializable {
+    private String name;
+
+    private String comment;
+
+    private String dataType;
+    //长度
+    private int    length;
+
+    //精度
+    private int precision;
+
+    //小数位数
+    private int scale;
+
+    private boolean notNull;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public String getDataType() {
+        return dataType;
+    }
+
+    public void setDataType(String dataType) {
+        this.dataType = dataType;
+    }
+
+    public int getLength() {
+        return length;
+    }
+
+    public void setLength(int length) {
+        this.length = length;
+    }
+
+    public int getPrecision() {
+        return precision;
+    }
+
+    public void setPrecision(int precision) {
+        this.precision = precision;
+    }
+
+    public int getScale() {
+        return scale;
+    }
+
+    public void setScale(int scale) {
+        this.scale = scale;
+    }
+
+    public boolean isNotNull() {
+        return notNull;
+    }
+
+    public void setNotNull(boolean notNull) {
+        this.notNull = notNull;
+    }
+
+}

+ 44 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/meta/table/Constraint.java

@@ -0,0 +1,44 @@
+package org.hswebframework.web.database.manager.meta.table;
+
+import java.io.Serializable;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class Constraint implements Serializable {
+    private String table;
+
+    private String column;
+
+    private Type type;
+
+    public String getTable() {
+        return table;
+    }
+
+    public void setTable(String table) {
+        this.table = table;
+    }
+
+    public String getColumn() {
+        return column;
+    }
+
+    public void setColumn(String column) {
+        this.column = column;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public void setType(Type type) {
+        this.type = type;
+    }
+
+    public enum Type {
+        PrimaryKey, ForeignKey, Unique, Check, Default
+    }
+}

+ 28 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/meta/table/ForeignConstraint.java

@@ -0,0 +1,28 @@
+package org.hswebframework.web.database.manager.meta.table;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class ForeignConstraint extends Constraint {
+    private String targetTable;
+
+    private String targetColumn;
+
+    public String getTargetTable() {
+        return targetTable;
+    }
+
+    public void setTargetTable(String targetTable) {
+        this.targetTable = targetTable;
+    }
+
+    public String getTargetColumn() {
+        return targetColumn;
+    }
+
+    public void setTargetColumn(String targetColumn) {
+        this.targetColumn = targetColumn;
+    }
+}

+ 32 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/src/main/java/org/hswebframework/web/database/manager/meta/table/TableMetadata.java

@@ -0,0 +1,32 @@
+package org.hswebframework.web.database.manager.meta.table;
+
+import org.hswebframework.web.database.manager.meta.ObjectMetadata;
+
+import java.util.List;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class TableMetadata extends ObjectMetadata {
+    private String comment;
+
+    private List<Constraint> constraints;
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public List<Constraint> getConstraints() {
+        return constraints;
+    }
+
+    public void setConstraints(List<Constraint> constraints) {
+        this.constraints = constraints;
+    }
+}

+ 39 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/pom.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-system-database-manager</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-system-database-manager-simple</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-database-manager-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+            <version>1.0.26</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-tests</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

+ 245 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/src/main/java/org/hswebframework/web/datasource/manager/simple/DefaultLocalTransactionExecutor.java

@@ -0,0 +1,245 @@
+package org.hswebframework.web.datasource.manager.simple;
+
+import org.hswebframework.ezorm.rdb.executor.SqlExecutor;
+import org.hswebframework.web.database.manager.SqlExecuteRequest;
+import org.hswebframework.web.database.manager.SqlExecuteResult;
+import org.hswebframework.web.database.manager.SqlInfo;
+import org.hswebframework.web.datasource.DataSourceHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class DefaultLocalTransactionExecutor implements TransactionExecutor {
+
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    private Queue<Execution> executionQueue = new LinkedList<>();
+
+    private SqlExecutor sqlExecutor;
+
+    private SqlRequestExecutor sqlRequestExecutor;
+
+    private String transactionId;
+
+    private String datasourceId;
+
+    private volatile boolean shutdown = false;
+
+    private TransactionStatus transactionStatus;
+
+    private TransactionTemplate transactionTemplate;
+
+    private boolean commit = false;
+
+    private volatile boolean running = false;
+
+    private CyclicBarrier waitToReady = new CyclicBarrier(2);
+
+    private CountDownLatch waitClose = new CountDownLatch(1);
+
+    public DefaultLocalTransactionExecutor(SqlExecutor sqlExecutor, String transactionId, String datasourceId, TransactionTemplate transactionTemplate) {
+        this.sqlExecutor = sqlExecutor;
+        this.transactionId = transactionId;
+        this.datasourceId = datasourceId;
+        this.transactionTemplate = transactionTemplate;
+    }
+
+    @Override
+    public String getTransactionId() {
+        return transactionId;
+    }
+
+    @Override
+    public String getDatasourceId() {
+        return datasourceId;
+    }
+
+    @Override
+    public void commit() {
+        commit = true;
+        shutdown = true;
+        waitToClose();
+    }
+
+    protected void waitToClose() {
+        try {
+            logger.debug("wait transaction {} close", transactionId);
+            if (!running) {
+                waitToReady.await();
+            }
+            waitClose.await();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void rollback() {
+        shutdown = true;
+        waitToClose();
+    }
+
+    public void setSqlExecutor(SqlExecutor sqlExecutor) {
+        this.sqlExecutor = sqlExecutor;
+    }
+
+    public void setSqlRequestExecutor(SqlRequestExecutor sqlRequestExecutor) {
+        this.sqlRequestExecutor = sqlRequestExecutor;
+    }
+
+    protected void buildDefaultSqlRequestExecutor() {
+        sqlRequestExecutor = (executor, sqlInfo) -> {
+            SqlExecuteResult result = new SqlExecuteResult();
+            Object executeResult = null;
+
+            switch (sqlInfo.getType().toUpperCase()) {
+                case "SELECT":
+                    executeResult = executor.list(sqlInfo.getSql());
+                    break;
+                case "INSERT":
+                case "UPDATE":
+                    executeResult = executor.update(sqlInfo.getSql());
+                    break;
+                case "DELETE":
+                    executeResult = executor.delete(sqlInfo.getSql());
+                    break;
+                default:
+                    executor.exec(sqlInfo.getSql());
+            }
+            result.setResult(executeResult);
+            result.setSqlInfo(sqlInfo);
+            return result;
+        };
+    }
+
+    @Override
+    public void run() {
+        try {
+            if (datasourceId != null) {
+                DataSourceHolder.switcher().use(datasourceId);
+            }
+            transactionStatus = transactionTemplate.getTransactionManager().getTransaction(transactionTemplate);
+            if (sqlRequestExecutor == null) {
+                buildDefaultSqlRequestExecutor();
+            }
+            while (!shutdown) {
+                logger.debug("wait sql execute request {}", transactionId);
+                waitToReady.await();
+                waitToReady.reset();
+                doExecute();
+            }
+        } catch (Exception e) {
+            rollback();
+            logger.error("execute sql error {}", transactionId, e);
+        } finally {
+            try {
+                if (commit) {
+                    logger.debug("Commit transaction {}", transactionId);
+                    transactionTemplate.getTransactionManager().commit(transactionStatus);
+                } else {
+                    logger.debug("Roll Back transaction {}", transactionId);
+                    transactionTemplate.getTransactionManager().rollback(transactionStatus);
+                }
+                waitClose.countDown();
+            } finally {
+                DataSourceHolder.switcher().reset();
+            }
+        }
+    }
+
+    protected void doExecute() {
+        Execution execution;
+        while ((execution = executionQueue.poll()) != null) {
+            running = true;
+            logger.debug("start execute sql {}", transactionId);
+            try {
+                List<SqlExecuteResult> requests = execution.request.getSql().stream()
+                        .map(sqlInfo -> {
+                            try {
+                                return sqlRequestExecutor.apply(sqlExecutor, sqlInfo);
+                            } catch (SQLException e) {
+                                throw new RuntimeException(e);
+                            }
+                        })
+                        .collect(Collectors.toList());
+                execution.callback.accept(requests);
+            } catch (Exception e) {
+                rollback();
+                execution.onError.accept(e);
+            }
+        }
+        running = false;
+    }
+
+    @Override
+    public List<SqlExecuteResult> execute(SqlExecuteRequest request) {
+        if (shutdown) {
+            throw new UnsupportedOperationException("transaction is close");
+        }
+        CountDownLatch countDownLatch = new CountDownLatch(1);
+        List<SqlExecuteResult> results = new ArrayList<>();
+
+        Exception[] exceptions = new Exception[1];
+
+        Execution execution = new Execution();
+        execution.request = request;
+        execution.callback = sqlExecuteResults -> {
+            results.addAll(sqlExecuteResults);
+            sqlExecuteResults.clear();
+            countDownLatch.countDown();
+        };
+        execution.onError = e -> {
+            exceptions[0] = e;
+            countDownLatch.countDown();
+        };
+        logger.debug("submit sql execute job {}", transactionId);
+        executionQueue.add(execution);
+        try {
+            if (!running)
+                waitToReady.await();
+            countDownLatch.await();
+            Exception exception;
+            if ((exception = exceptions[0]) != null) {
+                if (exception instanceof RuntimeException) {
+                    throw (RuntimeException) exception;
+                } else {
+                    throw new RuntimeException(exception);
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return results;
+    }
+
+    protected class Execution {
+        protected SqlExecuteRequest request;
+
+        protected Consumer<List<SqlExecuteResult>> callback;
+
+        protected Consumer<Exception> onError;
+    }
+
+    private interface SqlRequestExecutor {
+        SqlExecuteResult apply(SqlExecutor executor, SqlInfo sqlInfo) throws SQLException;
+    }
+
+}

+ 100 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/src/main/java/org/hswebframework/web/datasource/manager/simple/SimpleDatabaseManagerService.java

@@ -0,0 +1,100 @@
+package org.hswebframework.web.datasource.manager.simple;
+
+import org.hswebframework.ezorm.rdb.executor.SqlExecutor;
+import org.hswebframework.web.database.manager.DatabaseManagerService;
+import org.hswebframework.web.database.manager.SqlExecuteRequest;
+import org.hswebframework.web.database.manager.SqlExecuteResult;
+import org.hswebframework.web.database.manager.meta.ObjectMetadata;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+@Service
+public class SimpleDatabaseManagerService implements DatabaseManagerService {
+
+    private Map<String, TransactionExecutor> transactionExecutorMap = new ConcurrentHashMap<>();
+
+    private ExecutorService executorService;
+
+    private SqlExecutor sqlExecutor;
+
+    private TransactionTemplate transactionTemplate;
+
+    @PostConstruct
+    public void init() {
+        if (executorService == null) {
+            executorService = Executors.newFixedThreadPool(20);
+        }
+    }
+
+    @Autowired(required = false)
+    public void setExecutorService(ExecutorService executorService) {
+        this.executorService = executorService;
+    }
+
+    @Autowired
+    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
+        this.transactionTemplate = transactionTemplate;
+    }
+
+    @Autowired
+    public void setSqlExecutor(SqlExecutor sqlExecutor) {
+        this.sqlExecutor = sqlExecutor;
+    }
+
+    @Override
+    public String newTransaction(String datasourceId) {
+        String id = UUID.randomUUID().toString();
+        DefaultLocalTransactionExecutor executor = new DefaultLocalTransactionExecutor(sqlExecutor, id, datasourceId, transactionTemplate);
+        transactionExecutorMap.put(id, executor);
+        executorService.submit(executor);
+        return id;
+    }
+
+    @Override
+    public String newTransaction() {
+        return newTransaction(null);
+    }
+
+    @Override
+    public void commit(String transactionId) {
+        TransactionExecutor executor = transactionExecutorMap.get(transactionId);
+        if (executor != null)
+            executor.commit();
+        transactionExecutorMap.remove(transactionId);
+    }
+
+    @Override
+    public void rollback(String transactionId) {
+        TransactionExecutor executor = transactionExecutorMap.get(transactionId);
+        if (executor != null)
+            executor.rollback();
+        transactionExecutorMap.remove(transactionId);
+    }
+
+    @Override
+    public List<SqlExecuteResult> execute(String transactionId, SqlExecuteRequest request) {
+        TransactionExecutor executor = transactionExecutorMap.get(transactionId);
+        if (executor != null)
+            return executor.execute(request);
+        return null;
+    }
+
+    @Override
+    public Map<ObjectMetadata.ObjectType, List<ObjectMetadata>> getMetas(String datasourceId) {
+        return null;
+    }
+}

+ 24 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/src/main/java/org/hswebframework/web/datasource/manager/simple/TransactionExecutor.java

@@ -0,0 +1,24 @@
+package org.hswebframework.web.datasource.manager.simple;
+
+import org.hswebframework.web.database.manager.SqlExecuteRequest;
+import org.hswebframework.web.database.manager.SqlExecuteResult;
+
+import java.util.List;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public interface TransactionExecutor extends Runnable {
+    String getTransactionId();
+
+    String getDatasourceId();
+
+    void commit();
+
+    void rollback();
+
+    List<SqlExecuteResult> execute(SqlExecuteRequest request);
+
+}

+ 71 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/src/test/java/org/hswebframework/web/datasource/manager/simple/SimpleDatabaseManagerServiceTest.java

@@ -0,0 +1,71 @@
+package org.hswebframework.web.datasource.manager.simple;
+
+import com.alibaba.fastjson.JSON;
+import org.hswebframework.web.database.manager.DatabaseManagerService;
+import org.hswebframework.web.database.manager.SqlExecuteRequest;
+import org.hswebframework.web.database.manager.SqlExecuteResult;
+import org.hswebframework.web.database.manager.SqlInfo;
+import org.hswebframework.web.tests.SimpleWebApplicationTests;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+import static org.junit.Assert.*;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class SimpleDatabaseManagerServiceTest extends SimpleWebApplicationTests {
+
+    @Autowired
+    private DatabaseManagerService databaseManagerService;
+
+    @Test
+    public void testExecuteSql() throws InterruptedException, SQLException {
+        String id = databaseManagerService.newTransaction();
+        SqlExecuteRequest request = new SqlExecuteRequest();
+        SqlInfo sqlInfo = new SqlInfo();
+        sqlInfo.setSql("create table t_test(name varchar(32))");
+        sqlInfo.setType("create");
+
+        SqlInfo sqlInfo2 = new SqlInfo();
+        sqlInfo2.setSql("insert into t_test values('1234') ");
+        sqlInfo2.setType("insert");
+
+        request.setSql(Arrays.asList(sqlInfo));
+        List<SqlExecuteResult> results = databaseManagerService.execute(id, request);
+        System.out.println(JSON.toJSONString(results));
+        request.setSql(Arrays.asList(sqlInfo2));
+        int total = 1000;
+        CountDownLatch countDownLatch = new CountDownLatch(total);
+
+        for (int i = 0; i < total; i++) {
+            new Thread(() -> {
+                databaseManagerService.execute(id, request);
+                countDownLatch.countDown();
+            }).start();
+        }
+        countDownLatch.await();
+
+        sqlInfo = new SqlInfo();
+        sqlInfo.setSql("select * from t_test");
+        sqlInfo.setType("select");
+
+        request.setSql(Arrays.asList(sqlInfo));
+        results = databaseManagerService.execute(id, request);
+        System.out.println(JSON.toJSONString(results));
+
+        System.out.println(sqlExecutor.list("select * from t_test"));
+
+        databaseManagerService.rollback(id);
+        Thread.sleep(2000);
+        System.out.println(sqlExecutor.list("select * from t_test").size());
+
+    }
+}

+ 16 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-simple/src/test/resources/application.yml

@@ -0,0 +1,16 @@
+spring:
+    aop:
+        auto: true
+    datasource:
+       url : jdbc:h2:mem:dbm_test_mem
+       username : sa
+       password :
+       type: com.alibaba.druid.pool.DruidDataSource
+       driver-class-name : org.h2.Driver
+hsweb:
+    app:
+      name: 数据字典测试
+      version: 3.0.0
+logging:
+  level:
+    org.hswebframework: debug

+ 6 - 1
hsweb-system/hsweb-system-database-manager/pom.xml

@@ -10,6 +10,11 @@
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>hsweb-system-database-manager</artifactId>
-
+    <packaging>pom</packaging>
+    <description>数据库在线维护模块</description>
+    <modules>
+        <module>hsweb-system-database-manager-api</module>
+        <module>hsweb-system-database-manager-simple</module>
+    </modules>
 
 </project>