最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot+Beetl實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)庫(kù)DDL的示例代碼

 更新時(shí)間:2025年06月22日 08:37:51   作者:月生_  
最近公司里有一個(gè)新的需求,需要導(dǎo)出數(shù)據(jù)庫(kù)元數(shù)據(jù)表中存儲(chǔ)的表的 DDL 語(yǔ)句,而在元數(shù)據(jù)表中數(shù)據(jù)源的類型龐大,少則十幾種多則達(dá)到幾十種,各種數(shù)據(jù)庫(kù)類型都有,本篇文章就從這個(gè)模版引擎來(lái)入手介紹如何實(shí)現(xiàn)功能,需要的朋友可以參考下

序言

最近公司里有一個(gè)新的需求,需要導(dǎo)出數(shù)據(jù)庫(kù)元數(shù)據(jù)表中存儲(chǔ)的表的 DDL 語(yǔ)句,而在元數(shù)據(jù)表中數(shù)據(jù)源的類型龐大,少則十幾種多則達(dá)到幾十種,各種數(shù)據(jù)庫(kù)類型都有,比如常見(jiàn)就有 MySQL PostgreSQL Oracle SQL Server等等,而不同的數(shù)據(jù)庫(kù)其數(shù)據(jù)類型和語(yǔ)法都存在一些差異,如果在代碼中去處理工作量就太大了。所以我想到使用模版引擎來(lái)處理,現(xiàn)在市面上出現(xiàn)了一個(gè)新的模版引擎 Beetl。本篇文章就從這個(gè)模版引擎來(lái)入手介紹如何實(shí)現(xiàn)功能。代碼已經(jīng)提交到了我的 GitHub 倉(cāng)庫(kù)

Beetl

Beetl 的使用方式和 Thymeleaf、Freemarker 差不多,而且其語(yǔ)法簡(jiǎn)單,性能也優(yōu)于這兩者,目前在國(guó)內(nèi)已經(jīng)有一定的用戶群體。話不多說(shuō),具體的使用方式非常簡(jiǎn)單,大家看一下官網(wǎng)就會(huì)了,下面來(lái)說(shuō)功能怎么實(shí)現(xiàn)

代碼

使用前在SpringBoot中使用的時(shí)候需要先導(dǎo)入依賴,我測(cè)試的 SpringBoot 的版本為 3.2.1

<dependency>
    <groupId>com.ibeetl</groupId>
    <artifactId>beetl-spring-boot-starter-classic</artifactId>
    <version>3.19.1.RELEASE</version>
</dependency>

創(chuàng)建一下庫(kù)表,因?yàn)槟0嫖募谴鎯?chǔ)在數(shù)據(jù)庫(kù)中,方便后期維護(hù)

create table ddl_template
(
    id          int auto_increment
        primary key,
    name        varchar(255) not null,
    description varchar(255) null,
    created_at  timestamp    not null,
    updated_at  timestamp    null,
    created_by  varchar(255) null,
    updated_by  varchar(255) null,
    version     float        not null,
    db_type     varchar(255) not null,
    template    text         not null
)
    comment 'ddl模板表' charset = utf8mb4;

表創(chuàng)建完成后,我事先往這個(gè)表中添加了三條數(shù)據(jù),分別代表 MySQL、Oracle、PgSQL 的DDL 模版

MySQL:

drop table if exists `${table.tableCode}`;
create table ${table.tableCode}(
    <%
    for(field in fieldList){
    var code = field.code;
    var comment = field.comment;
    var type = field.type;
    var len = field.len;
    var scale = field.scale;
    var notNull = field.notNull;
    var autoIncrement = field.autoIncrement;
    var defaultValue = field.defaultValue;

    var last =  fieldLP.last;
    if (len != null) {
        if (len > 0) {
            var temp = "(" + len;
            if (scale != null) {
                if (scale > 0) {
                    temp = temp + "," + scale;
                }
            }
            temp = temp + ")";
            type = type + temp;
        }
    }
    %>
    `${field.code}` ${type}${autoIncrement ? " auto_increment":""}${notNull ? " not null":" null"}${defaultValue != null ? " default '" + defaultValue + "'" : "" }
     ${comment != null ? " comment '" + comment + "'":""}${!last ? ",":""}
    <%
    }
     %>
    <%
    if (primaryKey != null){
    %>
,primary key (${primaryKey})
    <%
    }
    %>
) comment = '${table.tableComment}';

Oracle:

create table "${table.tableCode}"(
    <%
    for(field in fieldList){
    var code = field.code;
    var comment = field.comment;
    var type = field.type;
    var len = field.len;
    var scale = field.scale;
    var primaryKey = field.primaryKey;
    var notNull = field.notNull;
    var defaultValue = field.defaultValue;

    var last =  fieldLP.last;
    if (len != null && type != 'date') {
        if (len > 0) {
            var temp = "(" + len;
            if (scale != null) {
                if (scale > 0) {
                    temp = temp + "," + scale;
                }
            }
            temp = temp + ")";
            type = type + temp;
        }
    }
    if (type == 'date') {
            defaultValue = null;
            notNull = false;
    }
    %>
    "${field.code}" ${type}${defaultValue != null ? " default '" + defaultValue + "'" : "" }${notNull ? " not null":" null"}${!last ? ",":""}
    <%
    }
     %>
     <%
     if (primaryKey != null){
     %>
,primary key ("${primaryKey}")
     <%
     }
     %>
);

comment on table "${table.tableCode}" is '${table.tableComment}';

<%
    for(field in fieldList){
    var code = field.code;
    var comment = field.comment;
    var last =  fieldLP.last;
    %>
comment on column "${table.tableCode}"."$[code]" is '${comment}';

    <%
    }
     %>

PgSQL:

drop table if exists "${table.tableCode}";

create table "${table.tableCode}"(
    <%
    for(field in fieldList){
    var code = field.code;
    var comment = field.comment;
    var type = field.type;
    var len = field.len;
    var scale = field.scale;
    var notNull = field.notNull;
    var autoIncrement = field.autoIncrement;
    var defaultValue = field.defaultValue;

    var last =  fieldLP.last;

    if (len != null) {
        if (len > 0) {
            var temp = "(" + len;
            if (scale != null) {
                if (scale > 0) {
                    temp = temp + "," + scale;
                }
            }
            temp = temp + ")";
            type = type + temp;
        }
    }

    %>
    "$[code]" ${type}${autoIncrement ? " generated always as identity" : ""}${notNull ? " not null" : ""}${defaultValue != null ? " default '" + defaultValue + "'" : "" }
    ${!last ? "," : ""}
    <%
    }
    %>
    <%
    if (primaryKey != null){
    %>
    ,primary key (${primaryKey})
    <%
    }
    %>
);

comment on table "${table.tableCode}" is '${table.tableComment}';

<%
for(field in fieldList){
    var code = field.code;
    var comment = field.comment;
    if (comment != null) {
%>
comment on column "${table.tableCode}"."$[code]" is '${comment}';
<%
    }
}
%>

準(zhǔn)備工作完成后,接下來(lái)開(kāi)發(fā)代碼,具體代碼如下:

@Bean
public GroupTemplate groupTemplate() throws Exception {
    StringTemplateResourceLoader loader = new StringTemplateResourceLoader();
    org.beetl.core.Configuration cfg = org.beetl.core.Configuration.defaultConfiguration();
    GroupTemplate gt = new GroupTemplate(loader, cfg);
    return gt;
}

這里使用的 StringTemplateResourceLoader 表示從字符串中來(lái)加載模板,也有其他的 ResourceLoader,比如 FileResourceLoader 表示從文件中加載模版,具體的看官網(wǎng)就可以了

/**
 * 單張表的ddl語(yǔ)句創(chuàng)建
 *
 * @return
 */
@PostMapping("/createDdl")
public void createDdl(@RequestParam("version") String version,@RequestParam("dbType") String dbType) {
    ddlTemplateService.createDdl(version, dbType);
}
@Override
public void createDdl(String version, String dbType) {
    DbEnum dbEnum = DbEnum.fromString(dbType);
    Assert.notNull(dbType, "數(shù)據(jù)庫(kù)類型不支持");

    switch (dbEnum) {
        case MYSQL:
            generateMysqlDdl(version, dbType, buildMySQLData());
            break;
        case ORACLE:
            generateOracleDdl(version, dbType, buildOracleData());
            break;
        case POSTGRESQL:
            generatePostgresqlDdl(version, dbType, buildPostgresqlData());
            break;
    }
}

這里支持的數(shù)據(jù)庫(kù)類型還比較少,大家可以后面擴(kuò)充

/**
 * 這里只是模擬一下,實(shí)際情況應(yīng)該是從數(shù)據(jù)庫(kù)中查詢的對(duì)應(yīng)的表及字段
 *
 * @return
 */
private Map<String, Object> buildMySQLData() {
    MySQLTable tableVO = MySQLTable.builder().tableCode("t_user").tableComment("用戶表").build();
    List<MySQLField> fieldVOList = List.of(
            MySQLField.builder().code("id").comment("主鍵").type("int").len(11).scale(0.0).autoIncrement(true).notNull(true).build(),
            MySQLField.builder().code("name").comment("姓名").type("varchar").len(50).scale(0.0).autoIncrement(false).defaultValue("").notNull(true).build(),
            MySQLField.builder().code("age").comment("年齡").type("int").len(11).scale(0.0).autoIncrement(false).notNull(true).build(),
            MySQLField.builder().code("email").comment("郵箱").type("varchar").len(50).scale(0.0).autoIncrement(false).defaultValue("").notNull(true).build(),
            MySQLField.builder().code("create_time").comment("創(chuàng)建時(shí)間").type("date").len(0).scale(0.0).autoIncrement(false).notNull(true).notNull(true).build()
    );
    return Map.of("table", tableVO, "fieldList", fieldVOList, "primaryKey", "id");
}

private Map<String, Object> buildOracleData() {
    OracleTable tableVO = OracleTable.builder().tableCode("t_user").tableComment("用戶表").build();
    List<OracleField> fieldVOList = List.of(
            OracleField.builder().code("id").comment("主鍵").type("NUMBER").len(11).scale(0.0).autoIncrement(true).notNull(true).build(),
            OracleField.builder().code("name").comment("姓名").type("varchar").len(50).scale(0.0).autoIncrement(false).defaultValue("").notNull(true).build(),
            OracleField.builder().code("age").comment("年齡").type("NUMBER").len(11).scale(0.0).autoIncrement(false).notNull(true).build(),
            OracleField.builder().code("email").comment("郵箱").type("varchar").len(50).scale(0.0).autoIncrement(false).defaultValue("").notNull(true).build(),
            OracleField.builder().code("create_time").comment("創(chuàng)建時(shí)間").type("date").len(0).scale(0.0).autoIncrement(false).notNull(true).notNull(true).build()
    );
    return Map.of("table", tableVO, "fieldList", fieldVOList, "primaryKey", "id");
}

private Map<String, Object> buildPostgresqlData() {
    PostgresqlTable tableVO = PostgresqlTable.builder().tableCode("t_user").tableComment("用戶表").build();
    List<PostgresqlField> fieldVOList = List.of(
            PostgresqlField.builder().code("id").comment("主鍵").type("integer").autoIncrement(true).notNull(true).build(),
            PostgresqlField.builder().code("name").comment("姓名").type("varchar").len(50).scale(0.0).autoIncrement(false).defaultValue("").notNull(true).build(),
            PostgresqlField.builder().code("age").comment("年齡").type("int").autoIncrement(false).notNull(true).build(),
            PostgresqlField.builder().code("email").comment("郵箱").type("varchar").len(50).scale(0.0).autoIncrement(false).defaultValue("").notNull(true).build(),
            PostgresqlField.builder().code("create_time").comment("創(chuàng)建時(shí)間").type("timestamp").len(0).scale(0.0).autoIncrement(false).notNull(true).notNull(true).build()
    );
    return Map.of("table", tableVO, "fieldList", fieldVOList, "primaryKey", "id");
}


private void generateMysqlDdl(String version, String dbType, Map<String, Object> data) {
    try {
        // 可以考慮將模版文件緩存
        Template template = groupTemplate.getTemplate(queryByUnique(version, dbType).getTemplate());
        template.binding(data);
        String render = template.render();
        log.info("生成MysqlDDL語(yǔ)句成功");
        FileUtil.writeUtf8String(render, "D:/ddl.sql");
    } catch (Exception e) {
        throw new RuntimeException("生成DDL語(yǔ)句失敗", e);
    }
}

private void generateOracleDdl(String version, String dbType, Map<String, Object> data) {
    try {
        // 可以考慮將模版文件緩存
        Template template = groupTemplate.getTemplate(queryByUnique(version, dbType).getTemplate());
        template.binding(data);
        String render = template.render();
        log.info("生成OracleDDL語(yǔ)句成功");
        FileUtil.writeUtf8String(render, "D:/ddl.sql");
    } catch (Exception e) {
        throw new RuntimeException("生成DDL語(yǔ)句失敗", e);
    }
}

private void generatePostgresqlDdl(String version, String dbType, Map<String, Object> data) {
    // 可以考慮將模版文件緩存
    Template template = groupTemplate.getTemplate(queryByUnique(version, dbType).getTemplate());
    template.binding(data);
    String render = template.render();
    log.info("生成PgSQLDDL語(yǔ)句成功");
    FileUtil.writeUtf8String(render, "D:/ddl.sql");
}

我這里運(yùn)行后會(huì)分別針對(duì)不同的數(shù)據(jù)庫(kù)類型來(lái)生成對(duì)應(yīng)的表 DDL 語(yǔ)句,效果如下:

MySQL

drop table if exists `t_user`;
create table t_user(
    `id` int(11) auto_increment not null
      comment '主鍵',
    `name` varchar(50) not null default ''
      comment '姓名',
    `age` int(11) not null
      comment '年齡',
    `email` varchar(50) not null default ''
      comment '郵箱',
    `create_time` date not null
      comment '創(chuàng)建時(shí)間'
,primary key (id)
) comment = '用戶表';

Oracle

create table "t_user"(
    "id" NUMBER(11) not null,
    "name" varchar(50) default '' not null,
    "age" NUMBER(11) not null,
    "email" varchar(50) default '' not null,
    "create_time" date null
,primary key ("id")
);

comment on table "t_user" is '用戶表';

comment on column "t_user"."id" is '主鍵';

comment on column "t_user"."name" is '姓名';

comment on column "t_user"."age" is '年齡';

comment on column "t_user"."email" is '郵箱';

comment on column "t_user"."create_time" is '創(chuàng)建時(shí)間';


PgSQL

drop table if exists "t_user";

create table "t_user"(
    "id" integer generated always as identity not null
    ,
    "name" varchar(50) not null default ''
    ,
    "age" int not null
    ,
    "email" varchar(50) not null default ''
    ,
    "create_time" timestamp not null
    
    ,primary key (id)
);

comment on table "t_user" is '用戶表';

comment on column "t_user"."id" is '主鍵';
comment on column "t_user"."name" is '姓名';
comment on column "t_user"."age" is '年齡';
comment on column "t_user"."email" is '郵箱';
comment on column "t_user"."create_time" is '創(chuàng)建時(shí)間';

這三個(gè) DDL 語(yǔ)句在對(duì)應(yīng)的數(shù)據(jù)庫(kù)里面是可以運(yùn)行

總結(jié)

這里采用數(shù)據(jù)庫(kù)存儲(chǔ)模版的方式比在代碼中硬編碼維護(hù)性要好,不然模版有改動(dòng)的話,還需要去修改代碼重新打包,總體下來(lái)并不是很難。

以上就是SpringBoot+Beetl實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)庫(kù)DDL的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Beetl動(dòng)態(tài)數(shù)據(jù)庫(kù)DDL的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺談Spring Boot日志框架實(shí)踐

    淺談Spring Boot日志框架實(shí)踐

    這篇文章主要介紹了淺談Spring Boot日志框架實(shí)踐,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • Java的ArrayList擴(kuò)容源碼解析

    Java的ArrayList擴(kuò)容源碼解析

    這篇文章主要介紹了Java的ArrayList擴(kuò)容源碼解析,通過(guò)動(dòng)態(tài)擴(kuò)容,ArrayList能夠在添加元素時(shí)保持高效的性能,擴(kuò)容操作是有一定開(kāi)銷的,但由于擴(kuò)容的時(shí)間復(fù)雜度為O(n),其中n是當(dāng)前元素個(gè)數(shù),所以平均情況下,每次添加元素的時(shí)間復(fù)雜度仍然是O(1),需要的朋友可以參考下
    2024-01-01
  • Java實(shí)現(xiàn)監(jiān)聽(tīng)UDP協(xié)議的指定端口并收到數(shù)據(jù)按照十六進(jìn)制輸出方式

    Java實(shí)現(xiàn)監(jiān)聽(tīng)UDP協(xié)議的指定端口并收到數(shù)據(jù)按照十六進(jìn)制輸出方式

    這篇文章主要介紹了Java實(shí)現(xiàn)監(jiān)聽(tīng)UDP協(xié)議的指定端口并收到數(shù)據(jù)按照十六進(jìn)制輸出方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Mybatis中單雙引號(hào)引發(fā)的慘案及解決

    Mybatis中單雙引號(hào)引發(fā)的慘案及解決

    這篇文章主要介紹了Mybatis中單雙引號(hào)引發(fā)的慘案及解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java實(shí)現(xiàn)發(fā)送手機(jī)短信語(yǔ)音驗(yàn)證功能代碼實(shí)例

    Java實(shí)現(xiàn)發(fā)送手機(jī)短信語(yǔ)音驗(yàn)證功能代碼實(shí)例

    這篇文章主要介紹了Java實(shí)現(xiàn)發(fā)送手機(jī)短信語(yǔ)音驗(yàn)證功能代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • SpringCloud服務(wù)實(shí)現(xiàn)同時(shí)使用eureka和nacos方法

    SpringCloud服務(wù)實(shí)現(xiàn)同時(shí)使用eureka和nacos方法

    這篇文章主要介紹了SpringCloud服務(wù)實(shí)現(xiàn)同時(shí)使用eureka和nacos方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-01-01
  • 簡(jiǎn)單聊聊RabbitMQ中的隊(duì)頭阻塞問(wèn)題

    簡(jiǎn)單聊聊RabbitMQ中的隊(duì)頭阻塞問(wèn)題

    這篇文章主要為大家詳細(xì)介紹了RabbitMQ中的隊(duì)頭阻塞問(wèn)題以及相關(guān)的解決方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-02-02
  • 詳解Java中ExceptionInInitializer錯(cuò)誤的解決方法

    詳解Java中ExceptionInInitializer錯(cuò)誤的解決方法

    ExceptionInInitializerError 是 Java 中的未經(jīng)檢查的異常,它是 Error 類的子類, 它屬于運(yùn)行時(shí)異常的類別,下面我們就來(lái)看看它的具體解決方法吧
    2024-02-02
  • java8新特性之Optional的深入解析

    java8新特性之Optional的深入解析

    這篇文章主要給大家介紹了關(guān)于java8新特性之Optional的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • Jersey Restful接口如何獲取參數(shù)的問(wèn)題

    Jersey Restful接口如何獲取參數(shù)的問(wèn)題

    這篇文章主要介紹了Jersey Restful接口如何獲取參數(shù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06

最新評(píng)論

和田县| 肥东县| 朔州市| 赣州市| 江都市| 邯郸县| 龙泉市| 阳春市| 灵石县| 清新县| 延安市| 兰坪| 永顺县| 余庆县| 易门县| 上虞市| 张家港市| 德庆县| 德安县| 象州县| 乌苏市| 留坝县| 海阳市| 长治市| 清水县| 奈曼旗| 贺州市| 文山县| 衡水市| 秭归县| 太仆寺旗| 安福县| 鄢陵县| 财经| 溆浦县| 达尔| 阳泉市| 江阴市| 来安县| 洮南市| 桃源县|