無需編程蚀腿,基于微軟mssql數(shù)據(jù)庫零代碼生成CRUD增刪改查RESTful API接口

無需編程程癌,基于微軟mssql數(shù)據(jù)庫零代碼生成CRUD增刪改查RESTful API接口

回顧

通過之前一篇文章 無需編程舷嗡,基于甲骨文oracle數(shù)據(jù)庫零代碼生成CRUD增刪改查RESTful API接口 的介紹,引入了FreeMarker模版引擎嵌莉,通過配置模版實現(xiàn)創(chuàng)建和修改物理表結構SQL語句进萄,并且通過配置oracle數(shù)據(jù)庫SQL模版,基于oracle數(shù)據(jù)庫锐峭,零代碼實現(xiàn)crud增刪改查中鼠。本文采用同樣的方式,很容易就可以支持微軟SQL Server數(shù)據(jù)庫沿癞。

MSSQL簡介

SQL Server 是Microsoft 公司推出的關系型數(shù)據(jù)庫管理系統(tǒng)援雇。具有使用方便可伸縮性好與相關軟件集成程度高等優(yōu)點,可從運行Microsoft Windows的電腦和大型多處理器的服務器等多種平臺使用椎扬。Microsoft SQL Server 是一個全面的數(shù)據(jù)庫平臺惫搏,使用集成的商業(yè)智能 (BI)工具提供了企業(yè)級的數(shù)據(jù)管理。Microsoft SQL Server 數(shù)據(jù)庫引擎為關系型數(shù)據(jù)和結構化數(shù)據(jù)提供了更安全可靠的存儲功能蚕涤,使您可以構建和管理用于業(yè)務的高可用和高性能的數(shù)據(jù)應用程序筐赔。

UI界面

通過課程對象為例,無需編程揖铜,基于MSSQL數(shù)據(jù)庫茴丰,通過配置零代碼實現(xiàn)CRUD增刪改查RESTful API接口和管理UI。

創(chuàng)建課程表


courseMeta.png

編輯課程數(shù)據(jù)


courseData.png

課程數(shù)據(jù)列表


courseList.png

通過DBeaver數(shù)據(jù)庫工具查詢mssql數(shù)據(jù)


DBeaver.png

定義FreeMarker模版

創(chuàng)建表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>

創(chuàng)建ca_course表

UI點擊創(chuàng)建表單之后天吓,后臺會轉換成對應的SQL腳本贿肩,最終創(chuàng)建物理表。

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'創(chuàng)建時間', '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';

修改表

freemarker.png

包括表結構和索引的修改龄寞,刪除等汰规,和創(chuàng)建表原理類似。

application.properties

需要根據(jù)需要配置數(shù)據(jù)庫連接驅動萄焦,無需重新發(fā)布控轿,就可以切換不同的數(shù)據(jù)庫冤竹。

#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數(shù)據(jù)庫實現(xiàn)原理,并且以課程對象為例茬射,零代碼實現(xiàn)了CRUD增刪改查RESTful API鹦蠕,后續(xù)介紹更多的數(shù)據(jù)庫,比如Mongodb等在抛。

實現(xiàn)方式 代碼量 時間 穩(wěn)定性
傳統(tǒng)開發(fā) 1000行左右 2天/人 5個bug左右
crudapi系統(tǒng) 0行 1分鐘 基本為0

綜上所述钟病,利用crudapi系統(tǒng)可以極大地提高工作效率和節(jié)約成本,讓數(shù)據(jù)處理變得更簡單刚梭!

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末肠阱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子朴读,更是在濱河造成了極大的恐慌屹徘,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衅金,死亡現(xiàn)場離奇詭異噪伊,居然都是意外死亡,警方通過查閱死者的電腦和手機氮唯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門鉴吹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人惩琉,你說我怎么就攤上這事豆励。” “怎么了瞒渠?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵良蒸,是天一觀的道長。 經常有香客問我在孝,道長诚啃,這世上最難降的妖魔是什么淮摔? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任私沮,我火速辦了婚禮,結果婚禮上和橙,老公的妹妹穿的比我還像新娘仔燕。我一直安慰自己,他們只是感情好魔招,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布晰搀。 她就那樣靜靜地躺著,像睡著了一般办斑。 火紅的嫁衣襯著肌膚如雪外恕。 梳的紋絲不亂的頭發(fā)上杆逗,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天,我揣著相機與錄音鳞疲,去河邊找鬼罪郊。 笑死,一個胖子當著我的面吹牛尚洽,可吹牛的內容都是我干的悔橄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼腺毫,長吁一口氣:“原來是場噩夢啊……” “哼癣疟!你這毒婦竟也來了?” 一聲冷哼從身側響起潮酒,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤睛挚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后急黎,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體竞川,經...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年叁熔,在試婚紗的時候發(fā)現(xiàn)自己被綠了委乌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡荣回,死狀恐怖遭贸,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情心软,我是刑警寧澤壕吹,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站删铃,受9級特大地震影響耳贬,放射性物質發(fā)生泄漏。R本人自食惡果不足惜猎唁,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一咒劲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧诫隅,春花似錦腐魂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至豁生,卻和暖如春兔毒,著一層夾襖步出監(jiān)牢的瞬間漫贞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工育叁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绕辖,地道東北人。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓擂红,卻偏偏與公主長得像仪际,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子昵骤,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內容