美文网首页java
java动态数据源(多种数据库)中自定义表(实体)的创建及增查删

java动态数据源(多种数据库)中自定义表(实体)的创建及增查删

作者: 木巽 | 来源:发表于2023-07-03 18:03 被阅读0次

我正在做一个开源的低代码平台:https://gitee.com/IElwin/ezlcp-java,了解代代码平台的都知道,会有自定义数据源、自定义表(实体)、自定义表单、自定义报表等功能。

关于自定义数据源,如果只支持一种数据库的话,开发起来就会容易些。目前很多平台是支持多种数据库的,如:MySQLOraclePostgreSQLSQL Server,还有的会支持国产的数据库,如:达梦人大金仓等。

如果表结构是固定的,我们可以使用MyBatisHibernateORM工具类库来操作表;但是需求中表结构是用户自定义的,可能随时变动,使用ORM工具就不适合了。那怎么实现这些用户自定义动态表的创建、修改表结构、查询、插入等操作呢?接下来比较一下各实现方案:

方法一:使用JdbcTemplate全手写SQL

当然直接用jdbc来实现也是可以的,但用spring的JdbcTemplate会更优雅一些,可以少写一些代码。我看过一个产品的源码就是用这种方式来实现的。使用的是策略设计模式,定义一个数据操作的接口,每一种数据库就写一个实现该接口的操作类。当进行数据库操作时,会根据DruidDataSource数据源的getDbType方法来获取数据库类型,找到相应的操作类Bean,再执行相应的方法。这是最基本也是最灵活的方案,但是会有很多代码量,也需要花大量的时间来测试。之前用过的那个产品在MySQL数据库下运行正常,切换到Oracle数据源时一大堆问题出现。我就想有没有这方面开源组件,节省开发时间和测试时间。

方法二:使用AnyLine

AnyLine是国内的开源java组件,官网地址:http://doc.anyline.org/,它底层的实现方式类似于第一种方法。使用时,如果要支持某一种数据,就引用该数据库的相关的Jar包,官方文档中写的支持多种数据库,还有些国产数据库也支持。完全开源免费的,也可以切换数据源,所以我就试用了一下,测试主要代码如下:

        service.setDataSource(dsName);
        Table table = service.metadata().table(null, null, tableName);
        if (null != table) {
            service.ddl().drop(table);
        }
        table = new Table(tableName);
        table.setComment("测试创建的表");
        table.addColumn("id", "varchar(64)").setPrimaryKey(true).setComment("主键");
        table.addColumn("name", "varchar(50)").setComment("姓名");
        table.addColumn("age", "int").setComment("年龄");
        table.addColumn("create_time", "datetime").setComment("创建时间");
        table.addColumn("create_by", "varchar(64)").setComment("创建人");
        service.ddl().create(table);
        //插入数据
        DataRow row = new DataRow();
        row.put("id","101");
        row.put("name","张三");
        String now= DateUtils.getTime();
        row.put("age",60);
        row.put("create_time",now);
        service.insert(tableName, row);
        //查询数据
        DataSet set = service.querys(tableName);
        service.setDefaultDataSource();

pom.xml文件相关内容如下:

     <!-- 每一种数据库要引用一个类库,还要引入该数据库的jdbc驱动程序 -->
        <dependency>
            <groupId>org.anyline</groupId>
            <artifactId>anyline-data-jdbc-postgresql</artifactId>
            <version>8.6.3-20230625</version>
        </dependency>
        <dependency>
            <groupId>org.anyline</groupId>
            <artifactId>anyline-data-jdbc-oracle</artifactId>
            <version>8.6.3-20230625</version>
        </dependency>
       <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.6.0</version>
        </dependency>
        <dependency>
            <groupId>com.oracle.database.jdbc</groupId>
            <artifactId>ojdbc8</artifactId>
            <version>23.2.0.0</version>
        </dependency>

就是先切换到指定的数据源,然后创建表,插入一条数据,再查询该表,最后切换回默认数据源。日期类型在MySQL数据库下,直接传new Date() 或者时间字符串都是可以的;但切换到PostgreSQL两种类型值都会报错了。说明AnyLine也不是很稳定,还需要测试以及对某种数据库特殊处理才可以。

方法三: 使用jDialects

jDialects项目地址:https://gitee.com/drinkjava2/jdialects,也是国内的免费开源组件,并不是很出名,但非常轻量极。官方的介绍:jDialects是一个Java数据库方言工具,支持80多种数据库方言,具有分页、函数变换、类型变换、DDL生成、JPA注解解析等功能,它通常与JDBC工具组合使用。
pom.xml引入:

<dependency>
    <groupId>com.github.drinkjava2</groupId>
    <artifactId>jdialects</artifactId>
    <version>5.0.13.jre8</version>
</dependency>

因为这个类库只负责生成SQL,至于SQL的执行还是需要引入相关的JDBC驱动程序的。测试代码如下:

        var ds = DruidUtils.getDataSource(dsId);
        var template = new JdbcTemplate(ds);
        TableModel t = new TableModel(tableName);
        t.comment("测试创建的表");
        t.column("id").VARCHAR(64).pkey().comment("主键");
        t.column("name").VARCHAR(50).comment("姓名");
        t.column("age").INTEGER().comment("年龄");
        t.column("create_time").TIMESTAMP().comment("创建时间");
        t.column("create_by").VARCHAR(64).comment("创建人");
        Dialect dialect = Dialect.guessDialect(ds);
        String[] ddlArray = dialect.toDropAndCreateDDL(t);
        for (String ddl : ddlArray) {
            template.execute(ddl);
        }
        String now = DateUtils.getTime();
        String sql = "insert into " + tableName + " (id,name,age,create_time) values('101','李明',18,'" + now + "')";
        template.execute(sql);

        sql = "select * from " + tableName;
        JsonResult result = JsonResult.getSuccessResult("common.handleSuccess");
        var data = template.queryForList(sql);

测试了MySQLPostgreSQL两种数据库都是可以正常运行的,所以就决定是你了。

方法四: 使用jOOQ

jOOQ官网:https://www.jooq.org/,看了教程觉得用起来很简单的;但是它是一个商用软件,虽然也有开源版本。开源版本只支持MySQLPostgreSQL还有一些小众数据库,而且只支持特定的版本(比如MySQL只支持8.0.31版,其他旧版本不支持),觉得开源版本太鸡肋,决定放弃试用。如果你不在乎钱的话可以使用,商业版也可以免费试用30天。

总结

最终的决定采用的方案是:先定义统一的操作接口(方法一、二中都有接口),然后建立一个默认的实现类(调用jDialects,应该可以兼容大多数常用的数据库);对于jDialects未实现的或者出错的数据库,再新建一个实现类(可继承默认实现类)来处理。

相关文章

  • python基础-03

    python操作mysql数据库 创建数据表 数据表的 增 删 查 改 增 查 改 删

  • 数据库操作

    FMDB 创建数据库 创建表 增 删 改 查 索引 事务 多表联查

  • 单表的 CURD 操作(第一讲)

    CURD 操作,即指对数据库中实体对象的增Create、改Update、查Read、删Delete操作。 自定义 ...

  • iOS FMDB

    iOS FMDB 数据库创建、增、删、改、查。 创建对象 创建表 integer,text:类型 primary ...

  • User的Dao类

    /**对数据库中的表进行增,删,改,查*/package com.nsu.dao; import java.net...

  • Flask数据库的增、删、改、查

    Flask数据库的增、删、改、查 1、增: 创建类的实例(数据库的行): 例如给article表中的title和c...

  • 数据库SQLite基本用法(一)

    数据库涉及到创建、增、删、改、查 创建数据表 关键字:CREATE TABLE CREATE TABLE [数据库...

  • Kotlin中Room的简单使用

    增加引用 apply 导出数据库建表语句 实体类 Dao 创建数据库 增 删 查 升级数据库 实体类,新增age字...

  • MySQL基础

    SQL学习 MySQL 数据库相关 表相关 表的增、删、改、查 首先先创建一个表teachercreate tab...

  • mongodb常用的操作

    帮助help 创建、切换数据库 增 删 改 查

网友评论

    本文标题:java动态数据源(多种数据库)中自定义表(实体)的创建及增查删

    本文链接:https://www.haomeiwen.com/subject/sbmqudtx.html