天天看點

jxTMS使用示例--類表同步的繼承

使用本示例需通過docker容器,請先下拉jxTMS的docker鏡像并按說明啟動tms容器,并從helloWorld開始嘗試。

jxTMS類表同步的繼承

繼承是面向對象程式設計的核心概念,也是軟體工程中提高代碼複用、降階系統複雜度、程式設計模型易于了解的關鍵性技術。是以jxTMS的一個設計目标就是:自定義的資料類也應具備繼承的能力。資料類的繼承非常簡單,因為不管是python還是java都是面向對象的程式設計語言,自然都支援類的繼承。但資料類是要映射到資料庫中的某個表的,也就是說資料類的繼承必須要解決資料庫中的相應的資料表在繼承時的操作簡化問題,否則就會違背jxTMS的根本目标:低成本快速定制。

這種為了確定資料類之間的繼承語義的資料操作邏輯,jxTMS稱之為類表同步。我們下面就來示範這種能力。

資料類的繼承

我們在data檔案中增加一個新的資料類:

class extDemo super demoData:
	field ID long primaryKey
	field Ext string len=32
;
           

注意和之前的demoData定義相比,多了【super demoData】,訓示extDemo資料類是從demoData資料類繼承而來的。

OK,我們現在就将data按用sftp管理jxTMS的代碼所述更新到/home/tms/codeDefine/demo/demo/demo1目錄中。

然後執行一次熱機重新整理,看看發生了什麼:

1、通過日志,我們看到在加載demo子產品時,系統報告:

2021-06-13 21:07:59.591 tty DEBUG [pool-3-thread-16] 資料表(extDemo)是否存在:false cn.ijingxi.tms.common.orm.jxORMobj.createTableInDB(jxORMobj.java:914)
2021-06-13 21:07:59.592 tty DEBUG [pool-3-thread-16] 建立資料表:extDemo cn.ijingxi.tms.common.orm.jxORMobj.createTableInDB(jxORMobj.java:917)
2021-06-13 21:07:59.592 tty DEBUG [pool-3-thread-16] CREATE TABLE extDemo(ID bigint NOT NULL PRIMARY KEY,Ext VARCHAR(32) NOT NULL) cn.ijingxi.tms.common.orm.jxORMobj.createTableInDB(jxORMobj.java:959)
           

即jxTMS在加載data檔案時,檢測到資料表(extDemo)不存在,随即根據data檔案中的定義自動建立了extDemo資料表。

2、我們檢視資料庫驗證一下:

mysql> use demo_6288;
mysql> desc extDemo;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| ID    | bigint(20)  | NO   | PRI | NULL    |       |
| Ext   | varchar(32) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
           

确實在資料庫中根據我們在data檔案中的定義建立了extDemo資料表。可是,按繼承的定義,extDemo不是也應該包括了demoData中定義的Type、Name等字段嗎?!請往下看。

建立extDemo對象

我們把sayHello函數修改一下:

@myModule.event('cmd', 'sayHello')
def sayHello(self, db, ctx):
	dd = pyORM.create(db,'extDemo')
	dd.Type = 'demo'
	dd.Name = 'Name-sayHello'
	dd.Ext = 'Ext-sayHello'
           

我們現在将capa.py檔案按用sftp管理jxTMS的代碼所述更新到/home/tms/codeDefine/demo/demo/demo1目錄中。

然後執行一次熱機重新整理後,再次點選快捷欄中的【示範->helloWorld】,然後點選【點我】按鈕。然後執行:

mysql> select * from extDemo;
+-------------------+--------------+
| ID                | Ext          |
+-------------------+--------------+
| 26600905801465938 | Ext-sayHello |
+-------------------+--------------+
1 row in set (0.00 sec)

mysql> select * from demoData;
+-------------------+--------+------+---------------------+---------------+
| ID                | NoUsed | Type | CreateTime          | Name          |
+-------------------+--------+------+---------------------+---------------+
|   103897269075998 |      0 | test | 2021-06-11 07:00:30 | ok            |
| 26600905801465938 |      0 | demo | 2021-06-13 13:20:42 | Name-sayHello |
+-------------------+--------+------+---------------------+---------------+
2 rows in set (0.00 sec)
           

可以看到現在在extDemo表中和demoData表中,同時多了一個ID相同的資料行。而這兩行的Ext、Type、Name也恰好是我們在sayHello所賦予的。即在資料庫層面,一個extDemo資料對象被拆分後分别放到extDemo資料表和demoData資料表中存儲,然後通過共同的ID主鍵進行關聯。

讀取extDemo對象

我們把helloWorld的prepareDisp函數修改一下:

@myModule.event('prepareDisp', 'helloWorld')
def helloWorld(self, db, ctx):
	#請把26600905801465938換成你查到的ID值
	dd = pyORM.getByID(db.getDBConn(),'extDemo',26600905801465938)
	self.setOutput('outText',utils.getMsg('{}.{}.{}/from:{}',dd.Type,dd.Name,dd.Ext,dd.ID))
           

我們現在将capa.py檔案按用sftp管理jxTMS的代碼所述更新到/home/tms/codeDefine/demo/demo/demo1目錄中。

然後執行一次熱機重新整理後,再次點選快捷欄中的【示範->helloWorld】然後看一下【說點啥】後的顯示内容。

示範結果表面,我們在用getByID讀取一個extDemo資料對象時,jxTMS會自動做一個extDemo和demoData兩資料表的聯合查詢【ID相等為條件】,然後将查詢出來的資料指派給建立出來的extDemo資料對象。

在資料源中,jxTMS也會自動關聯extDemo和demoData,大家可以嘗試着把sql檔案中的listDemoData做如下的修改【修改前最好把原來的listDemoData複制後改名為listDemoDataOld】:

sql listDemoData
from extDemo as ta
select ta.all
where ta.Type=='demo'
orderBy ta.CreateTime DESC;
           

我們現在将capa.py檔案按用sftp管理jxTMS的代碼所述更新到/home/tms/codeDefine/demo/demo/demo1目錄中。

然後執行一次熱機重新整理後,再次點選快捷欄中的【示範->listDemoData】然後看看能否顯示出正确的資料。

可以看到,雖然我們在from子句中隻寫了extDemo表,但jxTMS會自動為我們關聯demoData。

總結

jxTMS的類表同步的繼承能力,使得資料類被繼承後,在python中的使用就如同未繼承的資料類一樣,而jxTMS會自動在資料庫層面實作資料的正确存儲與同步讀取。這就完全不需要開發者在資料類繼承後還需要做任何額外的資料管理了,進而大大降低了對開發者的要求還提高了相關操作的可靠性。

注:由于擔心jxTMS所提供的資料表自動管理能力太過強大,導緻修改資料類定義時誤删除資料列,筆者不得不限制了這一能力:jxTMS隻會根據data檔案來建立資料庫中沒有過的同名資料表,但建立後絕不會根據data中資料類定義的變化就去修改資料庫表的定義。

即資料庫中資料表的定義如果要變動,開發者隻能手動進行調整,這是為了避免開發者随意修改data中資料類的定義,使得jxTMS根據這個修改删除了資料庫中的列,導緻資料丢失。而之前筆者反複說了,jxTMS不提供資料删除能力,即jxTMS的開發邏輯是:錯就錯了,但不能删。

也就是說,在設計資料類時,一定要想清楚,否則到時再想修改就隻能手動進行了。

那麼,如果我們一定需要修改資料類的定義呢?!簡單的很,我們這節說的不就是類表同步的繼承嗎!在原來的類上繼承出來一個新的資料類就好了,最多有些屬性現在不用了就是。而且更關鍵的是:這不會影響原有代碼,是以我們拷貝一下老代碼到新的事件響應函數中,然後老代碼不動,對新增資料在新的事件響應函數中處理就好了。

當然,即便我們有了類表同步的繼承能力,使得我們可以近乎随心所欲的擴充資料類,但畢竟每次繼承都是多做了一個表級的級聯,就資料庫的查詢來說,效率是會下降的,是以還是建議大家在設計資料類時,要盡可能的想清楚,為日後的擴充留點餘地。

注:jxTMS沒有限制繼承的層數,理論上講不管繼承了多少層,jxTMS都會自動沿着繼承層次完成所有父表的關聯。但關系資料庫中表的級聯是一個笛卡爾乘積的運算,是以級聯的多了,查詢效率肯定會下降

如果大家還對之前的那個問題【按繼承的定義,extDemo不是也應該包括了demoData中定義的Type、Name等字段嗎?!】有疑問,不了解jxTMS為什麼會把extDemo拆分為extDemo和demoData。

那麼請思考一下:

1、按照繼承的定義,子類也是基類,那麼extDemo對象是不是demoData對象?

2、反映到資料庫中,26600905801465938号的extDemo是不是也是26600905801465938号的demoData?

3、那如果extDemo也包括了demoData中定義的Type、Name等字段,那我們要查詢26600905801465938号的demoData時,系統該如何知道要從extDemo表中查而不是從demoData表中查呢?!