数据库探测器

前言

    年前的一些产品有对数据库(mysql、oracle、odps、elasticsearch。。。)进行结构探测以及相关的一些基本信息抓取,多个项目中都有牵涉到,一些功能也类似于navicat这样的软件功能,但该探测器更多的是代码层面,适用于一些对多种数据源进行管理的项目。代码地址https://github.com/ChenBoEason/detector 由于个人工作时间原因,博客介绍较少,原谅楼主的懒,后面将会一步步的完善,这只是一个很简单的工具,只是一个很小很小的个人项目,还在思考怎样去壮大它,也想早一点开源出来让有想法的朋友一起去发展它,完善它。

当前满足功能

1.对mysql、oracle、odps数据库进行结构以及基本信息探测。

2.支持基于数据配置进行sql语句生成(搭配前端界面可进行sql动态配置生成)。

3.支持功能函数,对数据进行过滤(类似于数据清洗标化,目前满足功能较少,还在完善中)。

 

核心代码

  顶层入口接口com.cbmiddleware.detector.Detector 方法如下,各个数据源根据个性化差异进行处理,

public interface Detector {
    /**
     * 探测
     *
     * @param detectRequest 探测请求参数
     * @return
     * @throws DetectorException
     */
    DetectResponse detect(DetectRequest detectRequest) throws DetectorException;

    /**
     * 同步回调探测
     *
     * @param detectRequest
     * @param threshold     探测参数回调阀值 如 100,当探测到100张表或列数达到1000时调用回调监听器
     * @param listener
     * @return
     * @throws DetectorException
     */
    void detect(DetectRequest detectRequest, Threshold threshold, DetectorActionListener<DetectResponse> listener) throws DetectorException;

    /**
     * 异步回调阀值探测
     *
     * @param detectRequest 探测请求参数
     * @param listener      回调监听器
     * @return
     * @throws DetectorException
     */
    void detectAsync(DetectRequest detectRequest, Threshold threshold, DetectorActionListener<DetectResponse> listener) throws DetectorException;

    /**
     * 测试连通性
     *
     * @param detectRequest
     * @return
     */
    boolean isConnect(DetectRequest detectRequest) throws DetectorException;

    /**
     * 探测表大小(存储大小,数据量)
     *
     * @param detectRequest
     * @return
     * @throws DetectorException
     */
    DetectResponse detectTableSize(DetectRequest detectRequest, List<String> tableNames) throws DetectorException;

    /**
     * 执行sql
     *
     * @param detectRequest
     * @param sql
     * @return
     * @throws DetectorException
     */
    DetectResponse executeSql(DetectRequest detectRequest, String sql) throws DetectorException;

    /**
     * 探测器类型
     *
     * @return
     */
    DetectorType detectorType();

    /**
     * 探测数据库类型
     *
     * @return
     */
    DataBaseType databaseType();
}

 

 

使用

探测mysql数据库表结构

@Slf4j
public class MysqlDetectorTest {

    private static Detector detector = new MysqlTableDetector();
    private static MysqlDetectRequest request = new MysqlDetectRequest();

    @Before
    public void init(){
        request.setUsername("用户名");
        request.setPassword("密码");
        request.setProject("项目名");
        request.setAddress("连接地址");
        request.setPort("3306");
    }

    @Test
    public void connectTest(){
        boolean connect = false;
        try {
            connect = detector.isConnect(request);
        } catch (DetectorException e) {
            e.printStackTrace();
        }

        System.out.println(connect);
    }

    @Test
    public void detect(){
        List<String> tableNames = new ArrayList<>();
      
        tableNames.add("standard_union_copy1");
        /* 设置后将会探测指定表名信息 */
        //request.setTableNames(tableNames);

        for (int i = 0; i < 1; i++) {
            new Thread(() -> {
                try {


                    MysqlDetectResponse response = (MysqlDetectResponse) detector.detect(request);

                    System.out.println(JSON.toJSONString(response));
                    System.out.println(response.getTableInfos().keySet());;
                } catch (DetectorException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    @Test
    public void sqlTest(){
        String sql = "SELECT * FROM validation_dic_group g\n" +
                "INNER JOIN validation_dic_data d on d.dic_key = g.dic_grp_key\n" +
                "where g.dic_grp_key = 'CVX_Right' limit 0,10";

        try {
            MysqlDetectExecuteSqlResponse response = (MysqlDetectExecuteSqlResponse)detector.executeSql(request, sql);
            System.out.println();
        } catch (DetectorException e) {
            e.printStackTrace();
        }
    }

}

探测oracle

public class OracleDetectorTest {

    private static Detector detector = null;
    private static OracleDetectRequest request = null;

    @Before
    public void init() {
        detector = new OracleTableDetector();
        request = new OracleDetectRequest();
        request.setUsername("sys as sysdba");
        request.setPassword("system");
        request.setProject("");
        request.setAddress("");
        request.setPort("1521");
        request.setSid("orcl");
        request.setTestConnection(false);
    }

    @Test
    public void detectorTest() {
        try {
            OracleDetectResponse response = (OracleDetectResponse) detector.detect(request);


            System.out.println(JSON.toJSONString(response));
        } catch (DetectorException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void detectorListenerTest() {
        Threshold threshold = new Threshold();
        threshold.setTableCount(1);
        threshold.setColumnCount(10);
        try {
            detector.detect(request, threshold, new DetectorActionListener<DetectResponse>() {
                @Override
                public void onResponse(DetectResponse detectResponse) {
                    OracleDetectResponse response = (OracleDetectResponse) detectResponse;

                    System.out.println(JSON.toJSONString(response));
                }

                @Override
                public void onFailure(Exception e) {

                }
            });


        } catch (DetectorException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void sqlTest(){
        String sql = "SELECT\n" +
                "\t* \n" +
                "FROM\n" +
                "\tDATAQULITY.MZ_GUAHAO1 mz \n" +
                "LEFT JOIN DATAQULITY.SYS_USER s on s.ID != mz.BINGRENID";

        try {
           OracleDetectExecuteSqlResponse response = (OracleDetectExecuteSqlResponse) detector.executeSql(request, sql);
            System.out.println(JSON.toJSONString(response));
        } catch (DetectorException e) {
            e.printStackTrace();
        }
    }
}

odps的探测

@Slf4j
public class OdpsDetectorTest {

    private static Detector detector = null;

    private static OdpsDetectRequest request = null;

    @Before
    public void init(){
        detector = new OdpsTableDetector();
        OdpsDetectRequest request = new OdpsDetectRequest();
        request.setAccessId("");
        request.setAccessKey("");
        request.setProject("");
        request.setUrl("");
        request.setTunnelUrl("");
    }


    @Test
    public void connectTest(){
        try {
            doConnect(detector, request);
        } catch (DetectorException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void detectTest(){
        try {
            detect(detector, request);
        } catch (DetectorException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void tableSizetest(){
        try {
            detectTableSize(detector, request);
        } catch (DetectorException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void detectByListenerTest(){
        try {
            detectByListener(detector, request);
        } catch (DetectorException e) {
            e.printStackTrace();
        }
    }



    private static void detectByListener(Detector detector, OdpsDetectRequest request) throws DetectorException{
        Threshold threshold = new Threshold();

        threshold.setTableCount(10);

        detector.detect(request, threshold, new DetectorActionListener<DetectResponse>() {
            @Override
            public void onResponse(DetectResponse detectResponse) {
                OdpsDetectResponse response = (OdpsDetectResponse) detectResponse;
                log.info("listener response result:{}", JSON.toJSONString(response));
            }

            @Override
            public void onFailure(Exception e) {

            }
        });
    }

    private static void executeSql(Detector detector, OdpsDetectRequest request) throws DetectorException {
        OdpsDetectExecuteSqlResponse response = (OdpsDetectExecuteSqlResponse)detector.executeSql(request, "select * from ods_mh_yhqdyrmyy_zy_feiyong1_his limit 20;");
        log.info("result :{}",JSON.toJSONString(response));
    }

    private static void detectTableSize(Detector detector, OdpsDetectRequest request) throws DetectorException {
        List<String> tableNames = new ArrayList<>();
        
        request.setTableNames(tableNames);
        OdpsDetectTableSizeResponse response = (OdpsDetectTableSizeResponse)detector.detectTableSize(request, tableNames);
        log.info("result :{}",JSON.toJSONString(response));
    }

    private static void detect(Detector detector, OdpsDetectRequest request) throws DetectorException {
        OdpsDetectResponse response = (OdpsDetectResponse) detector.detect(request);
        log.info("result :{}",JSON.toJSONString(response));
    }

    private static void doConnect(Detector detector, OdpsDetectRequest request) throws DetectorException {

        boolean connect = detector.isConnect(request);
        log.info("connect status :{}", connect);
    }
}

sql动态生成测试

   下面测试只是个人的一个基于sql转换为代码,使用场景更多的是搭配前端进行配置生成。

public class MysqlSqlGeneratorTest {


    @Test
    public void threeTableJoin() {

        String sql = "SELECT\n" +
                "\tt.id AS id,\n" +
                "\tt.project AS project,\n" +
                "\tt.table_name AS tableName,\n" +
                "\tc.column_comment AS columnComment,\n" +
                "\tc.column_name AS columnName,\n" +
                "\ts.url as jdbcUrl,\n" +
                "\ts.username as dbUsername,\n" +
                "\tem.data_element_column_name as elementColmnName,\n" +
                "\tNULL AS emptyColumn \n" +
                "FROM\n" +
                "\tmed_detect_table t\n" +
                "\tINNER JOIN med_detect_table_column c ON c.table_name = t.name\n" +
                "\tLEFT JOIN med_data_source s on  t.db_code = s.db_code\n" +
                "\tLEFT JOIN med_data_element_mapping_info em on em.column_name = c.column_name and em.name = 'chenbo'\n" +
                "WHERE\n" +
                "\tt.db_code = 'xBbGIw2C' \n" +
                "\tAND t.creator = 'SYSTEM'\n" +
                "\tAND t.gmt_create <= NOW()";

        GenerateSqlConfInfo generateSqlConf = new GenerateSqlConfInfo();

        ExtraCondition extraCondition = new ExtraCondition();
        extraCondition.setTableName("med_data_source");
        extraCondition.setConditionType(ConditionType.gt);
        extraCondition.setColumnName("time");
        extraCondition.setValue("%s");
        extraCondition.setRelation(ColumnRelation.and);

        System.out.println(JSON.toJSONString(extraCondition));

        /**
         * 构建 med_detect_table 表配置
         */
        QueryTable detectTable = new QueryTable("med_detect_table", "t");
        /* gmt_create 条件 */
        ConditionInfo gmtContidion = new ConditionInfo("gmt_create", ConditionType.lte, new Date(), ColumnRelation.and);
        ConditionInfo creatorCondition = new ConditionInfo("creator", ConditionType.eq, "SYSTEM", ColumnRelation.and, gmtContidion);
        ConditionInfo dbCodeCondition = new ConditionInfo("db_code", ConditionType.eq,"xBbGIw2C",null, creatorCondition);


        /* 设置基表where条件 */
        generateSqlConf.setWhere(dbCodeCondition);

        /**
         * 构建med_detect_table_column表配置
         */
        QueryTable columnTable = new QueryTable("med_detect_table_column", "c");
        /* 与med_detect_table inner join */
        columnTable.setTableRelation(TableRelation.inner_join);
        columnTable.setConditionInfo(new ConditionInfo("table_name", ConditionType.eq, "t", "name"));

        /**
         * med_data_source
         */
        QueryTable datasourceTable = new QueryTable("med_data_source", "s");
        /* 与med_detect_table left join */
        datasourceTable.setTableRelation(TableRelation.left_join);
        datasourceTable.setConditionInfo(new ConditionInfo("db_code", ConditionType.eq, "t", "db_code"));

        /**
         * med_data_element_mapping_info
         */
        QueryTable dataElementTable = new QueryTable("med_data_element_mapping_info", "em");
        /* 与med_detect_table_column left join */
        dataElementTable.setTableRelation(TableRelation.left_join);
        dataElementTable.setConditionInfo(new ConditionInfo("column_name", ConditionType.eq, "c", "column_name"));


        List<QueryTable> queryTables = new ArrayList<>();
        /* med_detect_table_column 和med_data_element_mapping_info与med_detect_table关联 */
        queryTables.add(columnTable);
        //columnTable.setQueryTables(datasourceTable);
       // queryTables.add(datasourceTable);
        queryTables.add(datasourceTable);
        detectTable.setQueryTables(queryTables);

        /* med_data_element_mapping_info 与构建med_detect_table_column表配置关联 */
        List<QueryTable> columnQueryTables = new ArrayList<>();
        columnQueryTables.add(dataElementTable);
        detectTable.setQueryTables(columnQueryTables);

        generateSqlConf.setQueryTable(detectTable);

        /**
         * 返回字段
         */
        List<QueryColumn> returnColumns = new ArrayList<>();

        returnColumns.add(new QueryColumn("t", "id", "id"));
        returnColumns.add(new QueryColumn("t", "project", "project"));
        returnColumns.add(new QueryColumn("t", "table_name", "tableName"));
        returnColumns.add(new QueryColumn("c", "column_comment", "columnComment"));


        QueryColumn queryColumn = new QueryColumn("c", "column_name", "columnName");


        ColumnCaseWhen columnCaseWhen = new ColumnCaseWhen();
        columnCaseWhen.setTableAlias("c");
        columnCaseWhen.setColumnName("column_name");

        /**
         * case when
         */
        /*List<CaseWhenCondition> conditions = new ArrayList<>();
        columnCaseWhen.setConditions(conditions);

        conditions.add(new CaseWhenCondition("eason", ConditionType.eq, "chenbo"));

        conditions.add(new CaseWhenCondition(1, ConditionType.eq, "one"));

        queryColumn.setFunctionParam(columnCaseWhen);*/
        returnColumns.add(queryColumn);



        returnColumns.add(new QueryColumn(null, null, "columnName"));

        returnColumns.add(new QueryColumn("s", "url", "jdbcUrl"));
        returnColumns.add(new QueryColumn("s", "username", "dbUsername"));
        returnColumns.add(new QueryColumn("em", "data_element_column_name", "elementColmnName"));

        generateSqlConf.setReturnColumns(returnColumns);

        SqlGenerator sqlGenerator = new MysqlSqlGenerator();

        /*try {
            sqlGenerator.join(extraCondition, generateSqlConf.getQueryTable(), 0, 50);
        } catch (DetectorException e) {
            e.printStackTrace();
        }*/

        String generateSql = null;
        try {
            System.out.println(JSON.toJSONString(generateSqlConf));
            generateSql = sqlGenerator.generate(generateSqlConf);
        } catch (DetectorException e) {
            e.printStackTrace();
        }

        /*Map<String, Object> sqlConfMap = new HashMap<>(2);
        sqlConfMap.put("extraCondition", extraCondition);
        sqlConfMap.put("sqlConfInfo", generateSqlConf);
        //System.out.println(JSON.toJSONString(sqlConfMap));
        System.out.println(JSON.toJSONString(extraCondition));
        System.out.println(JSON.toJSONString(generateSqlConf));*/
    }

    @Test
    public void twoTableJoin() {

        SqlGenerator sqlGenerator = new MysqlSqlGenerator();


        String sql = "SELECT\n" +
                "\tt.id as id,\n" +
                "\tt.project as project,\n" +
                "\tt.table_name as tableName,\n" +
                "\tc.column_comment as columnComment,\n" +
                "\tc.column_name as columnName\n" +
                "FROM\n" +
                "\tmed_detect_table t\n" +
                "\tINNER JOIN med_detect_table_column c ON c.table_name = t.table_name \n" +
                "WHERE\n" +
                "\tt.db_code = 'xBbGIw2C' \n" +
                "\tAND t.creator = 'SYSTEM'";

        GenerateSqlConfInfo generateSqlConf = new GenerateSqlConfInfo();

        /**
         * 构建 med_detect_table 表配置
         */
        QueryTable detectTable = new QueryTable("med_detect_table", "t");

        ConditionInfo dbCodeCondition = new ConditionInfo("db_code", ConditionType.eq,
                "xBbGIw2C",
                null,
                new ConditionInfo("creator", ConditionType.eq, "SYSTEM", ColumnRelation.and));

        generateSqlConf.setWhere(dbCodeCondition);

        /**
         * 构建med_detect_table_column表配置
         */
        QueryTable columnTable = new QueryTable("med_detect_table_column", "c");
        columnTable.setTableRelation(TableRelation.inner_join);
        columnTable.setConditionInfo(new ConditionInfo("table_name", ConditionType.eq, "t", "table_name"));

        /**
         * 两表关联
         */
        List<QueryTable> queryTables = new ArrayList<>();
        queryTables.add(columnTable);
        detectTable.setQueryTables(queryTables);

        generateSqlConf.setQueryTable(detectTable);

        /**
         * 字段设置
         */
        List<QueryColumn> returnColumns = new ArrayList<>();

        returnColumns.add(new QueryColumn("t", "id", "id"));
        returnColumns.add(new QueryColumn("t", "project", "project"));
        returnColumns.add(new QueryColumn("t", "table_name", "tableName"));
        returnColumns.add(new QueryColumn("c", "column_comment", "columnComment"));
        returnColumns.add(new QueryColumn("c", "column_name", "columnName"));
        returnColumns.add(new QueryColumn(null, null, "columnName"));

        generateSqlConf.setReturnColumns(returnColumns);


        String generateSql = null;
        try {
            generateSql = sqlGenerator.generate(generateSqlConf);
        } catch (DetectorException e) {
            e.printStackTrace();
        }
        //System.out.println(generateSql);

        //System.out.println(JSON.toJSONString(generateSqlConf));
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
地理探测器(地理信息系统,GIS)是一种用于收集、存储、管理、分析和展示地理数据的软件工具。安装地理探测器需要以下步骤: 1. 确定操作系统:首先,您需要确定您计算机的操作系统是哪种类型(例如Windows、Mac或Linux),以确保选择适合的GIS软件安装包。 2. 下载GIS软件:根据您的操作系统选择一个合适的GIS软件,比如ArcGIS、QGIS或MapInfo。您可以从官方网站或其他可靠的来源下载安装文件。 3. 执行安装程序:一旦您下载了GIS软件的安装文件,双击该文件以启动安装程序。通常,您将被要求同意软件许可协议和选择安装位置。 4. 安装依赖组件:某些GIS软件可能需要安装一些依赖组件(如Java Runtime Environment或.NET Framework)。根据软件安装程序的提示,确保正确安装这些组件。 5. 运行GIS软件:安装完成后,您可以在计算机上找到并运行GIS软件。单击图标或在开始菜单中找到相应的程序,并双击打开。 6. 配置设置:一旦GIS软件运行起来,您可能需要进行一些初始配置,如选择语言、设置默认存储路径或连接到数据库等。 7. 导入地理数据:要开始使用地理探测器,您需要导入地理数据。这可以通过从文件中加载数据、连接到外部数据库或通过网络获取数据来完成。 8. 数据分析和可视化:一旦您导入了地理数据,即可使用GIS的各种功能进行数据分析和可视化。您可以创建地图、执行空间分析、生成图表等等。 总之,安装地理探测器需要下载并安装适合您操作系统的GIS软件,执行安装程序,并可能需要安装一些依赖组件。完成安装后,您可以开始导入地理数据,并使用GIS软件的各种功能进行数据分析和可视化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值