無需程式設計,基於微軟mssql資料庫零程式碼生成CRUD增刪改查RESTful API介面
無需程式設計,基於微軟mssql資料庫零程式碼生成CRUD增刪改查RESTful API介面
回顧
通過之前一篇文章 無需程式設計,基於甲骨文oracle資料庫零程式碼生成CRUD增刪改查RESTful API介面 的介紹,引入了FreeMarker模版引擎,通過配置模版實現建立和修改物理表結構SQL語句,並且通過配置oracle資料庫SQL模版,基於oracle資料庫,零程式碼實現crud增刪改查。本文采用同樣的方式,很容易就可以支援微軟SQL Server資料庫。
MSSQL簡介
SQL Server 是Microsoft 公司推出的關係型資料庫管理系統。具有使用方便可伸縮性好與相關軟體整合程度高等優點,可從執行Microsoft Windows的電腦和大型多處理器的伺服器等多種平臺使用。Microsoft SQL Server 是一個全面的資料庫平臺,使用整合的商業智慧 (BI)工具提供了企業級的資料管理。Microsoft SQL Server 資料庫引擎為關係型資料和結構化資料提供了更安全可靠的儲存功能,使您可以構建和管理用於業務的高可用和高效能的資料應用程式。
UI介面
通過課程物件為例,無需程式設計,基於MSSQL資料庫,通過配置零程式碼實現CRUD增刪改查RESTful API介面和管理UI。
建立課程表
編輯課程資料
課程資料列表
通過DBeaver資料庫工具查詢mssql資料
定義FreeMarker模版
建立表create-table.sql.ftl
CREATE TABLE "${tableName}" ( <#list columnEntityList as columnEntity> <#if columnEntity.dataType == "BOOL"> "${columnEntity.name}" BIT<#if columnEntity.defaultValue??> DEFAULT <#if columnEntity.defaultValue == "true">1<#else>0</#if></#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "INT"> "${columnEntity.name}" INT<#if columnEntity.autoIncrement == true> IDENTITY(1, 1)</#if><#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "BIGINT"> "${columnEntity.name}" BIGINT<#if columnEntity.autoIncrement == true> IDENTITY(1, 1)</#if><#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "FLOAT"> "${columnEntity.name}" FLOAT<#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "DOUBLE"> "${columnEntity.name}" DOUBLE<#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "DECIMAL"> "${columnEntity.name}" DECIMAL<#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "DATE"> "${columnEntity.name}" DATE<#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "TIME"> "${columnEntity.name}" TIME<#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "DATETIME"> "${columnEntity.name}" DATETIME<#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "TIMESTAMP"> "${columnEntity.name}" TIMESTAMP<#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "CHAR"> "${columnEntity.name}" CHAR(${columnEntity.length})<#if columnEntity.defaultValue??> DEFAULT '${columnEntity.defaultValue}'</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "VARCHAR"> "${columnEntity.name}" VARCHAR(${columnEntity.length})<#if columnEntity.defaultValue??> DEFAULT '${columnEntity.defaultValue}'</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "PASSWORD"> "${columnEntity.name}" VARCHAR(200)<#if columnEntity.defaultValue??> DEFAULT '${columnEntity.defaultValue}'</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "ATTACHMENT"> "${columnEntity.name}" VARCHAR(4000)<#if columnEntity.defaultValue??> DEFAULT '${columnEntity.defaultValue}'</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "TEXT"> "${columnEntity.name}" VARCHAR(4000)<#if columnEntity.defaultValue??> DEFAULT '${columnEntity.defaultValue}'</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "LONGTEXT"> "${columnEntity.name}" TEXT<#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "BLOB"> "${columnEntity.name}" BINARY<#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#elseif columnEntity.dataType == "LONGBLOB"> "${columnEntity.name}" BINARY<#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> <#else> "${columnEntity.name}" VARCHAR(200)<#if columnEntity.defaultValue??> DEFAULT ${columnEntity.defaultValue}</#if><#if columnEntity.nullable != true> NOT NULL</#if><#if columnEntity_has_next>,</#if> </#if> </#list> ); <#list columnEntityList as columnEntity> <#if columnEntity.indexType?? && columnEntity.indexType == "PRIMARY"> ALTER TABLE "${tableName}" ADD CONSTRAINT "${columnEntity.indexName}" PRIMARY KEY ("${columnEntity.name}"); </#if> <#if columnEntity.indexType?? && columnEntity.indexType == "UNIQUE"> ALTER TABLE "${tableName}" ADD CONSTRAINT "${columnEntity.indexName}" UNIQUE("${columnEntity.name}"); </#if> <#if columnEntity.indexType?? && (columnEntity.indexType == "INDEX" || columnEntity.indexType == "FULLTEXT")> CREATE INDEX "${columnEntity.indexName}" ON "${tableName}" ("${columnEntity.name}"); </#if> </#list> <#if indexEntityList??> <#list indexEntityList as indexEntity> <#if indexEntity.indexType?? && indexEntity.indexType == "PRIMARY"> ALTER TABLE "${tableName}" ADD CONSTRAINT "${indexEntity.name}" PRIMARY KEY (<#list indexEntity.indexLineEntityList as indexLineEntity>"${indexLineEntity.columnEntity.name}"<#if indexLineEntity_has_next>,</#if></#list>); </#if> <#if indexEntity.indexType?? && indexEntity.indexType == "UNIQUE"> ALTER TABLE "${tableName}" ADD CONSTRAINT "${indexEntity.name}" UNIQUE(<#list indexEntity.indexLineEntityList as indexLineEntity>"${indexLineEntity.columnEntity.name}"<#if indexLineEntity_has_next>,</#if></#list>); </#if> <#if indexEntity.indexType?? && (indexEntity.indexType == "INDEX" || indexEntity.indexType == "FULLTEXT")> CREATE INDEX "${indexEntity.name}" ON "${tableName}" (<#list indexEntity.indexLineEntityList as indexLineEntity>"${indexLineEntity.columnEntity.name}"<#if indexLineEntity_has_next>,</#if></#list>); </#if> </#list> </#if> EXEC sp_addextendedproperty 'MS_Description', N'${caption}', 'SCHEMA', N'dbo','TABLE', N'${tableName}'; <#list columnEntityList as columnEntity> EXEC sp_addextendedproperty 'MS_Description', N'${columnEntity.caption}', 'SCHEMA', N'dbo','TABLE', N'${tableName}', 'COLUMN', N'${columnEntity.name}'; </#list>
建立ca_course表
UI點選建立表單之後,後臺會轉換成對應的SQL指令碼,最終建立物理表。
CREATE TABLE "ca_course" ( "id" BIGINT IDENTITY(1, 1) NOT NULL, "name" VARCHAR(200) NOT NULL, "classHour" INT, "score" FLOAT, "teacher" VARCHAR(200), "fullTextBody" VARCHAR(4000), "createdDate" DATETIME NOT NULL, "lastModifiedDate" DATETIME ); ALTER TABLE "ca_course" ADD CONSTRAINT "primary_key" PRIMARY KEY ("id"); CREATE INDEX "ft_fulltext_body" ON "ca_course" ("fullTextBody"); EXEC sp_addextendedproperty 'MS_Description', N'課程', 'SCHEMA', N'dbo','TABLE', N'ca_course'; EXEC sp_addextendedproperty 'MS_Description', N'編號', 'SCHEMA', N'dbo','TABLE', N'ca_course', 'COLUMN', N'id'; EXEC sp_addextendedproperty 'MS_Description', N'課程名稱', 'SCHEMA', N'dbo','TABLE', N'ca_course', 'COLUMN', N'name'; EXEC sp_addextendedproperty 'MS_Description', N'課時', 'SCHEMA', N'dbo','TABLE', N'ca_course', 'COLUMN', N'classHour'; EXEC sp_addextendedproperty 'MS_Description', N'學分', 'SCHEMA', N'dbo','TABLE', N'ca_course', 'COLUMN', N'score'; EXEC sp_addextendedproperty 'MS_Description', N'教師', 'SCHEMA', N'dbo','TABLE', N'ca_course', 'COLUMN', N'teacher'; EXEC sp_addextendedproperty 'MS_Description', N'全文索引', 'SCHEMA', N'dbo','TABLE', N'ca_course', 'COLUMN', N'fullTextBody'; EXEC sp_addextendedproperty 'MS_Description', N'建立時間', 'SCHEMA', N'dbo','TABLE', N'ca_course', 'COLUMN', N'createdDate'; EXEC sp_addextendedproperty 'MS_Description', N'修改時間', 'SCHEMA', N'dbo','TABLE', N'ca_course', 'COLUMN', N'lastModifiedDate';
修改表
包括表結構和索引的修改,刪除等,和建立表原理類似。
application.properties
需要根據需要配置資料庫連線驅動,無需重新發布,就可以切換不同的資料庫。
#mssql
spring.datasource.url=jdbc:sqlserver://localhost:1433;SelectMethod=cursor;DatabaseName=crudapi
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.username=sa
spring.datasource.password=Mssql1433
小結
本文主要介紹了crudapi支援mssql資料庫實現原理,並且以課程物件為例,零程式碼實現了CRUD增刪改查RESTful API,後續介紹更多的資料庫,比如Mongodb等。
實現方式 | 程式碼量 | 時間 | 穩定性 |
---|---|---|---|
傳統開發 | 1000行左右 | 2天/人 | 5個bug左右 |
crudapi系統 | 0行 | 1分鐘 | 基本為0 |
綜上所述,利用crudapi系統可以極大地提高工作效率和節約成本,讓資料處理變得更簡單!
crudapi簡介
crudapi是crud+api組合,表示增刪改查介面,是一款零程式碼可配置的產品。使用crudapi可以告別枯燥無味的增刪改查程式碼,讓您更加專注業務,節約大量成本,從而提高工作效率。
crudapi的目標是讓處理資料變得更簡單,所有人都可以免費使用!
無需程式設計,通過配置自動生成crud增刪改查RESTful API,提供後臺UI管理業務資料。基於主流的開源框架,擁有自主智慧財產權,支援二次開發。
demo演示
crudapi屬於產品級的零程式碼平臺,不同於自動程式碼生成器,不需要生成Controller、Service、Repository、Entity等業務程式碼,程式執行起來就可以使用,真正0程式碼,可以覆蓋基本的和業務無關的CRUD RESTful API。
官網地址:https://crudapi.cn
測試地址:https://demo.crudapi.cn/crudapi/login
附原始碼地址
GitHub地址
https://github.com/crudapi/crudapi-admin-web
Gitee地址
https://gitee.com/crudapi/crudapi-admin-web
由於網路原因,GitHub可能速度慢,改成訪問Gitee即可,程式碼同步更新。