Jelajahi Sumber

优化数据库管理

周浩 9 tahun lalu
induk
melakukan
5f6f3fee77

+ 100 - 0
hsweb-web-controller/src/main/java/org/hsweb/web/controller/system/DatabaseManagerController.java

@@ -0,0 +1,100 @@
+package org.hsweb.web.controller.system;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import org.hsweb.ezorm.meta.DatabaseMetaData;
+import org.hsweb.ezorm.meta.FieldMetaData;
+import org.hsweb.ezorm.meta.TableMetaData;
+import org.hsweb.ezorm.render.SqlAppender;
+import org.hsweb.ezorm.render.SqlRender;
+import org.hsweb.web.bean.po.user.User;
+import org.hsweb.web.core.authorize.annotation.Authorize;
+import org.hsweb.web.core.exception.AuthorizeException;
+import org.hsweb.web.core.exception.AuthorizeForbiddenException;
+import org.hsweb.web.core.message.ResponseMessage;
+import org.hsweb.web.core.utils.WebUtil;
+import org.hsweb.web.service.form.DynamicFormService;
+import org.hsweb.web.service.system.DataBaseManagerService;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Created by zhouhao on 16-6-30.
+ */
+@RestController
+@RequestMapping("/database")
+@Authorize(module = "database")
+public class DatabaseManagerController {
+    @Resource
+    private DataBaseManagerService dataBaseManagerService;
+
+    @RequestMapping(value = "/tables", method = RequestMethod.GET)
+    @Authorize(action = "R")
+    public ResponseMessage showTables() throws SQLException {
+        return ResponseMessage.ok(dataBaseManagerService.getTableList())
+                .include(TableMetaData.class, "name", "alias", "comment", "fields")
+                .include(FieldMetaData.class, "name", "alias", "comment", "dataType", "properties")
+                .onlyData();
+    }
+
+    @RequestMapping(value = "/exec", method = RequestMethod.POST)
+    public ResponseMessage exec(@RequestBody String sql) throws Exception {
+        String[] list = sql.split("[\n]");
+        List<SqlAppender> sqlList = new LinkedList<>();
+        SqlAppender[] tmp = {new SqlAppender()};
+        Arrays.asList(list).stream()
+                .filter(s -> !s.startsWith("--") && s.trim().length() != 0)
+                .forEach(s1 -> {
+                    if (s1.trim().endsWith(";")) {
+                        s1 = s1.trim();
+                        tmp[0].add(s1.substring(0, s1.length() - 1));
+                        sqlList.add(tmp[0]);
+                        tmp[0] = new SqlAppender();
+                    } else {
+                        tmp[0].add(s1);
+                    }
+                });
+        if (!tmp[0].isEmpty()) sqlList.add(tmp[0]);
+        List<String> sqlStringList = new ArrayList<>();
+        User user = WebUtil.getLoginUser();
+        for (SqlAppender appender : sqlList) {
+            String sqlLine = appender.toString().trim();
+            String type = sqlLine.split("[ ]")[0];
+            if (!user.hasAccessModuleAction("database", type.toLowerCase()))
+                throw new AuthorizeForbiddenException("权限不足");
+            sqlStringList.add(sqlLine);
+        }
+        return ResponseMessage.ok(dataBaseManagerService.execSql(sqlStringList));
+    }
+
+    @RequestMapping(value = "/sql/alter", method = RequestMethod.POST)
+    public ResponseMessage showAlterSql(@RequestBody JSONObject jsonObject) throws Exception {
+        return ResponseMessage.ok(dataBaseManagerService.createAlterSql(createTableMetaDataByJson(jsonObject)));
+    }
+
+    @RequestMapping(value = "/sql/create", method = RequestMethod.POST)
+    public ResponseMessage showCreateSql(@RequestBody JSONObject jsonObject) throws Exception {
+        return ResponseMessage.ok(dataBaseManagerService.createCreateSql(createTableMetaDataByJson(jsonObject)));
+    }
+
+    protected TableMetaData createTableMetaDataByJson(JSONObject jsonObject) {
+        TableMetaData tableMetaData = new TableMetaData();
+        tableMetaData.setName(jsonObject.getString("name"));
+        tableMetaData.setComment(jsonObject.getString("comment"));
+        JSONArray jsonArray = jsonObject.getJSONArray("fields");
+        for (int i = 0; i < jsonArray.size(); i++) {
+            FieldMetaData field = jsonArray.getObject(i, FieldMetaData.class);
+            tableMetaData.addField(field);
+        }
+        return tableMetaData;
+    }
+}

+ 46 - 0
hsweb-web-service-impl-common/src/main/java/org/hsweb/web/service/impl/DatabaseMetaDataFactoryBean.java

@@ -0,0 +1,46 @@
+package org.hsweb.web.service.impl;
+
+import org.hsweb.ezorm.meta.DatabaseMetaData;
+import org.hsweb.ezorm.render.dialect.H2DatabaseMeta;
+import org.hsweb.ezorm.render.dialect.MysqlDatabaseMeta;
+import org.hsweb.ezorm.render.dialect.OracleDatabaseMeta;
+import org.hsweb.web.core.Install;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.stereotype.Component;
+
+/**
+ * Created by zhouhao on 16-7-1.
+ */
+@Component
+public class DatabaseMetaDataFactoryBean implements FactoryBean<DatabaseMetaData> {
+
+    @Override
+    public DatabaseMetaData getObject() throws Exception {
+        DatabaseMetaData databaseMetaData = null;
+        switch (Install.getDatabaseType()) {
+            case "mysql":
+                databaseMetaData = new MysqlDatabaseMeta();
+                break;
+            case "oracle":
+                databaseMetaData = new OracleDatabaseMeta();
+                break;
+            case "h2":
+                databaseMetaData = new H2DatabaseMeta();
+                break;
+        }
+        if (databaseMetaData == null)
+            throw new UnsupportedOperationException();
+        databaseMetaData.init();
+        return databaseMetaData;
+    }
+
+    @Override
+    public Class<?> getObjectType() {
+        return DatabaseMetaData.class;
+    }
+
+    @Override
+    public boolean isSingleton() {
+        return false;
+    }
+}

+ 79 - 13
hsweb-web-service-impl-common/src/main/java/org/hsweb/web/service/impl/system/DataBaseManagerServiceImpl.java

@@ -1,20 +1,36 @@
 package org.hsweb.web.service.impl.system;
 
+import org.hsweb.ezorm.executor.EmptySQL;
+import org.hsweb.ezorm.executor.SQL;
 import org.hsweb.ezorm.executor.SqlExecutor;
+import org.hsweb.ezorm.meta.DatabaseMetaData;
 import org.hsweb.ezorm.meta.TableMetaData;
+import org.hsweb.ezorm.meta.expand.SimpleMapWrapper;
 import org.hsweb.ezorm.meta.parser.MysqlTableMetaParser;
 import org.hsweb.ezorm.meta.parser.OracleTableMetaParser;
 import org.hsweb.ezorm.meta.parser.TableMetaParser;
+import org.hsweb.ezorm.render.SqlRender;
+import org.hsweb.ezorm.render.dialect.H2DatabaseMeta;
+import org.hsweb.ezorm.render.dialect.MysqlDatabaseMeta;
+import org.hsweb.ezorm.render.dialect.OracleDatabaseMeta;
+import org.hsweb.ezorm.render.support.simple.SimpleSQL;
+import org.hsweb.ezorm.run.simple.SimpleDatabase;
 import org.hsweb.web.core.Install;
 import org.hsweb.web.core.exception.BusinessException;
+import org.hsweb.web.service.impl.DatabaseMetaDataFactoryBean;
 import org.hsweb.web.service.system.DataBaseManagerService;
 import org.hsweb.web.service.system.SqlExecuteProcess;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.Resource;
 import java.sql.SQLException;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 数据库管理服务实现类
@@ -26,35 +42,85 @@ import java.util.List;
  */
 @Service(value = "dataBaseManagerService")
 public class DataBaseManagerServiceImpl implements DataBaseManagerService {
+
     @Resource
     private SqlExecutor sqlExecutor;
 
+    @Autowired(required = false)
     private TableMetaParser tableMetaParser;
 
-    @PostConstruct
-    public void init() {
-        switch (Install.getDatabaseType()) {
-            case "mysql":
-                tableMetaParser = new MysqlTableMetaParser(sqlExecutor);
-                break;
-            case "oracle":
-                tableMetaParser = new OracleTableMetaParser(sqlExecutor);
-                break;
-        }
-    }
+    @Autowired
+    private DatabaseMetaDataFactoryBean databaseMetaDataFactoryBean;
 
     @Override
     public List<TableMetaData> getTableList() throws SQLException {
         if (tableMetaParser == null) {
-            throw new BusinessException("表结构解析器不支持");
+            throw new BusinessException("不支持的数据库");
         }
         return tableMetaParser.parseAll();
     }
 
     @Override
-    public void executeSQL(String sql, SqlExecuteProcess process) throws SQLException {
+    @Transactional(rollbackFor = Throwable.class)
+    public List<Map<String, Object>> execSql(List<String> sqlList) throws SQLException {
+        List<Map<String, Object>> response = new LinkedList<>();
+        for (String s : sqlList) {
+            Map<String, Object> msg = new LinkedHashMap<>();
+            msg.put("sql", s);
+            String type = s.split("[ ]")[0];
+            msg.put("type", type.toLowerCase());
+            switch (type.toLowerCase()) {
+                case "delete":
+                    msg.put("total", sqlExecutor.delete(new SimpleSQL(s)));
+                    break;
+                case "insert":
+                    msg.put("total", sqlExecutor.insert(new SimpleSQL(s)));
+                    break;
+                case "update":
+                    msg.put("total", sqlExecutor.update(new SimpleSQL(s)));
+                    break;
+                case "select":
+                    List<Map<String, Object>> data = sqlExecutor.list(new SimpleSQL(s), new SimpleMapWrapper() {
+                        @Override
+                        public void setUp(List<String> columns) {
+                            msg.put("columns", columns);
+                        }
+                    });
+                    msg.put("data", data);
+                    break;
+                default:
+                    sqlExecutor.exec(new SimpleSQL(s));
+                    msg.put("total", 1);
+                    break;
+            }
+            response.add(msg);
+        }
+        return response;
+    }
 
+    @Override
+    public String createAlterSql(TableMetaData newTable) throws Exception {
+        DatabaseMetaData databaseMetaData = databaseMetaDataFactoryBean.getObject();
+        databaseMetaData.putTable(tableMetaParser.parse(newTable.getName()));
+        SQL sql = databaseMetaData.getRenderer(SqlRender.TYPE.META_ALTER).render(newTable, true);
+        if (sql instanceof EmptySQL) return "";
+        StringBuilder builder = new StringBuilder(sql.getSql());
+        builder.append(";\n");
+        if (sql.getBinds() != null && !sql.getBinds().isEmpty())
+            sql.getBinds().forEach(bindSQL -> builder.append(bindSQL.getSql().getSql()).append(";\n"));
+        return builder.toString();
     }
 
+    @Override
+    public String createCreateSql(TableMetaData newTable) throws Exception {
+        DatabaseMetaData databaseMetaData = databaseMetaDataFactoryBean.getObject();
+        SQL sql = databaseMetaData.getRenderer(SqlRender.TYPE.META_CREATE).render(newTable, true);
+        if (sql instanceof EmptySQL) return "";
+        StringBuilder builder = new StringBuilder(sql.getSql());
+        builder.append(";\n");
+        if (sql.getBinds() != null && !sql.getBinds().isEmpty())
+            sql.getBinds().forEach(bindSQL -> builder.append(bindSQL.getSql().getSql()).append(";\n"));
+        return builder.toString();
+    }
 
 }

+ 5 - 7
hsweb-web-service-interface/src/main/java/org/hsweb/web/service/system/DataBaseManagerService.java

@@ -4,6 +4,7 @@ import org.hsweb.ezorm.meta.TableMetaData;
 
 import java.sql.SQLException;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 数据库管理服务,用于获取数据库中的表结构等操作
@@ -20,12 +21,9 @@ public interface DataBaseManagerService {
      */
     List<TableMetaData> getTableList() throws SQLException;
 
+    List<Map<String,Object>> execSql(List<String> sqlList) throws SQLException;
 
-    /**
-     * 执行sql语句,多条sql语句使用[;\n]分割
-     *
-     * @param sql     sql语句
-     * @param process 执行过程回调,每执行一个sql都应该调用对应的回调方法
-     */
-   void executeSQL(String sql, SqlExecuteProcess process) throws SQLException;
+    String createAlterSql(TableMetaData newTable)throws Exception;
+
+    String createCreateSql(TableMetaData newTable)throws Exception;
 }