天天看點

jxTMS使用示例--資料庫查詢

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

jxTMS的查詢

上一節中我們示範了資料庫中的表的定義和ORM操作,本節我們主要示範條件查詢。大部分情況下,我們是:

  • 查詢出資料顯示到一個web界面的資料表中供使用者檢視
  • 使用者點選某行的某個工具條,jxTMS再執行相應的響應函數對該行資料進行處理

本節我們先示範如何從資料庫中查詢資料顯示到一個web界面的資料表中。

資料源的定義

jxTMS中将一個查詢語句稱為一個資料源,資料源的定義是在sql檔案中以類SQL的文法進行定義的。請在demo1目錄中建立一個名為sql的檔案,然後輸入:

#請注意:我們用的是類sql文法,是以和sql文法是有一點差別的
sql listDemoData
#from子句要在select子句前
from demoData as ta
#all相當于sql中的*,即全部讀取
select ta.all
#其where子句中的相等比較是==,兩個等号
where ta.Type=='test'
orderBy ta.CreateTime DESC;
           

注:目前的where子句中的條件都是and連接配接,or連接配接的條件要先轉換為and連接配接

每個資料源定義語句,以sql開頭,以英文分号結尾,具體文法可參考sql資料源.。

listDemoData資料源在使用時必須使用全名,而資料源的全名是【子產品名.資料源名】,則示例中的全名應為:demo.listDemoData。其含義是查詢所有Type是test的demoData對象。

對應的資料表

為了顯示listDemoData查詢出來的資料,我們還需要定義一個資料表。我們在web檔案中添加如下的定義【具體文法可參考資料表控件】:

web listDemoData type div;
web listDemoDatat1 bind tableTotalCount parent listDemoData type table title="demoData清單",width=900,pagination=true,query=search,queryParam={'listTable':'listDemoDatat1'};
with listDemoDatat1 col ID head ID hide=true;
with listDemoDatat1 col CreateTime head 建立時間 width=150;
with listDemoDatat1 col Type head 類型 width=100;
with listDemoDatat1 col Name head 名字 width=80;
with listDemoDatat1 col NoUsed head 已删除 width=80;
           

上述文本,定義了一個listDemoData的界面,該界面的主體是listDemoDatat1資料表,該資料表是一個分頁表【pagination=true,預設每頁15行】,由于是分頁表,是以必須綁定tableTotalCount,jxTMS會在初始時,先查詢符合條件的資料行總數,以便于分頁控件的初始化【确定頁數等】,query、,queryParam屬性也都必須按示例書寫,其中queryParam是一個json類型的屬性,其必須将listTable值,指定為本資料表的名字,由于本資料庫名為listDemoDatat1,是以listTable的值就必須設定為listDemoDatat1,否則無法正确顯示資料。

listDemoDatat1資料表,一共定義了5列,分别對應demoData中的五個屬性,但由于ID一般都不需要顯示,是以使用了hide屬性,其它可見列都定義了width屬性,大家一會可以觀察一下效果。

注1:這裡定義的其實是各列的相對寬度,listDemoDatat1表我們定義了900的寬,表中各列的實際寬度就是:

本列的相對寬度 * 900 /各列相對寬度之和
           

注2:ID不顯示出來,還要寫在這裡的原因很簡單,如果有針對各行【即針對每個demoData對象】的操作,這些操作都需要以ID來定位是對哪一行的操作。後面會示範如何使用這樣的ID

增加入口

想顯示上面定義的這個資料表,需要一個入口才能被我們找到後使用,是以我們需要在op.py中為listDemoData增加一個入口:

@biz.Motion('demo.demo1','disp','listDemoData')
@biz.OPDescr
def op1(json):
	json.setShortcut('示範'.decode('utf-8'),'listDemoData')
	json.setParam('objType','demoData').setParam('dispType','list').setParam('dataSource','demo.listDemoData')
           

對照上節helloWorld的入口定義,我們會發現listDemoData多了三條setParam語句。setParam是用來為入口設定參數的,為了listDemoData能正确的執行,我們為其設定了三個參數:

  • objType:從資料庫查詢出來的資料,我們應将其轉換為哪種類型的資料對象
  • dispType:對于資料表來說,必須固定為list
  • dataSource:指定本次查詢的資料源的全名

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

然後執行一次熱機重新整理.。由于我們在左側快捷欄中增加了一個入口,而快捷欄是每次登入後一次性加載的,是以我們得登出再次登入後才能看到剛添加的入口。

再次登入後,點選快捷欄中的【示範->listDemoData】,看看顯示效果:

jxTMS使用示例--資料庫查詢

注:由于我們隻建立了一個demoData對象,是以隻有一行。是以最下面的分頁欄處隻有一頁

顯示詳情

上面說了ID為什麼被隐藏起來,現在我們就來看看如何使用這個隐藏起來的ID。我們先在web檔案中增加一個demoData的詳情界面:

web dispDemoData type div;
web dispDemoDatat1 parent dispDemoData type table title="世界,你好",width=900;
with dispDemoDatat1 row 0 col c0 web n type text text='類型:',width=100;
with dispDemoDatat1 row 0 col c1 web n bind demoType type text width=350;
with dispDemoDatat1 row 0 col c2 web n type text text='名稱:',width=100;
with dispDemoDatat1 row 0 col c3 web n bind demoName type text width=350;
           

同一行中的列叫什麼無所謂,但不能重名,否則前一個會丢失掉。

然後在capa.py檔案中增加dispDemoData的prepareDisp事件響應函數:

@myModule.event('prepareDisp', 'dispDemoData')
def dispDemoData(self, db, ctx):
	dd = pyORM.getByID(db.getDBConn(),'demoData',self.getInput('ID'))
	self.setOutput('demoType',dd.Type)
	self.setOutput('demoName',dd.Name)
           

然後,還要在listDemoData表中增加一行:

with listDemoDatat1 col op1 head 顯示詳情 web n type a width=80,capaname='demo.demo1',motion=disp,
	demand=dispDemoData,primary=true,text='檢視',require=[{"paramName":"ID"}];
           

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

然後執行一次熱機重新整理,點選快捷欄中的【示範->listDemoData】,看看顯示效果。

大家會看到清單中多出了一列,大家點選【檢視】這個工具條,看看會發生什麼。

大家請回頭仔細想一下我們做了什麼:

  • 為了顯示某個對象的詳情,我們定義了一個針對該對象的詳情顯示界面
  • 為了将對象的詳細資訊顯示出來,是以我們定義了該詳情界面的prepareDisp事件響應函數,用來在加載完該界面後,從資料庫中讀取相應的資料對象,然後用該資料對象的屬性對詳情界面進行初始化
  • 前面講過,我們的任何操作都需要一個入口,是以我們還需要為詳情界面準備一個入口,由于檢視詳情檢視的是listDemoData表中的每行資料的詳情,是以其入口隻能依附在該表中,是以我們又在listDemoDatat1中增加了一個op1列,專門用于放置檢視詳情的入口。

此外,dispDemoData的prepareDisp函數是如何知道自己應該顯示哪個對象的詳情呢?!這就用到了我們開始藏起來的那個ID列了,require屬性就是用來給dispDemoData操作準備參數的,我們這個指定了其隻有一個參數,參數名是ID,由于本行中恰好有一列的列名就叫做ID,jxTMS就會取該列的值作為參數送給dispDemoData函數。

資料加工

我們上面是直接将資料庫中的資料顯示出來,但如果需要顯示加工後的資料該怎麼辦呢?比如,年紀超過70,我們在清單顯示時,想加一個特殊提醒等等。我們先對dispDemoData做下簡單的修改:

web listDemoData type div;
web listDemoDatat1 bind tableTotalCount parent listDemoData type table title="demoData清單",width=900,pagination=true,query=search,queryParam={'listTable':'listDemoDatat1'};
with listDemoDatat1 col demoID head demoID hide=true;
with listDemoDatat1 col demoCreateTime head 建立時間 width=150;
with listDemoDatat1 col demoType head 類型 width=100;
with listDemoDatat1 col demoName head 名字 width=80;
with listDemoDatat1 col demoTypeName head 類型名字 width=180;
with listDemoDatat1 col demoNoUsed head 已删除 width=80;
with listDemoDatat1 col op1 head 顯示詳情 web n type a width=80,capaname='demo.demo1',motion=disp,
	demand=dispDemoData,primary=true,text='檢視',require=[{"paramName":"demoID"}];
           

可以看到,我們把每列的列名都加了個demo,這主要是我們程式設計時,最好給所有的名字都起的具有一定的業務含義,讓大家一看就知道是幹什麼用的,這可以大幅度降低數量混用的可能性。此外還增加了一個demoTypeName的列。

注:由于我們把ID改成了demoID,是以大家仔細看一下最後一行op1的定義中,require的參數也必須跟着改

然後我們在capa.py函數中增加一個dispAffairInfo函數:

#json是listDemoDatat1資料表中的一行
#jo是資料庫中demoData表中每一行所轉換成的demoData資料對象
def dispAffairInfo(self,db,ctx,json, jo):
	#将jo對象的ID屬性值設定給demoID列
	json.set("demoID", jo.ID)
	json.set("demoCreateTime", jo.CreateTime)
	json.set("demoType", utils.getMsg('{}-type',jo.Type))
	json.set("demoName", utils.getMsg('{}-name',jo.Name))
	#給demoTypeName列設定資料
	json.set("demoTypeName", utils.getMsg('{}-{}',jo.Type,jo.Name))
	json.set("demoNoUsed", jo.NoUsed)
           

上面我們在op1中把require的參數名改了,是以dispDemoData的prepareDisp事件響應函數也得跟着把輸入參數名從ID改為demoID:

@myModule.event('prepareDisp', 'dispDemoData')
def dispDemoData(self, db, ctx):
	dd = pyORM.getByID(db.getDBConn(),'demoData',self.getInput('demoID'))
	self.setOutput('demoType',dd.Type)
	self.setOutput('demoName',dd.Name)
           

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

然後執行一次熱機重新整理,點選快捷欄中的【示範->listDemoData】,看看顯示效果。

在jxTMS中,以預設方式執行的資料表查詢,在資料查詢完畢後,準備送出到前端的時候,都會逐行調用dispAffairInfo函數對每一行輸出都進行資料處理,如果沒有重載dispAffairInfo函數的話,預設的dispAffairInfo函數隻是簡單的将jo這個資料對象的所有屬性輸出到json中。

而我們上面因為重載了dispAffairInfo函數,是以會把讀取到的資料逐行調用上面的dispAffairInfo函數,而在我們的dispAffairInfo函數中,我們就可以對資料進行加工後再顯示給使用者了。

直接輸出

大家應該看出來了,上面講的查詢輸出,需要先轉換為一個資料對象,然後再逐行調用dispAffairInfo函數進行資料加工,如果我們不需要資料加工,同時又想輸出的資料列名都是demoType這樣帶有業務語義的,那能不能不要這麼麻煩呢?

當然能,我們隻要兩步就可以了:

1、修改sql定義增加别名:

#是以請一定注意:相等是==,兩個等号
sql listDemoData
from demoData as ta
select ta.ID as demoID,ta.CreateTime as demoCreateTime,ta.Type as demoType,ta.Name as demoName
where ta.Type=='test'
orderBy ta.CreateTime DESC;
           

2、修改op.py檔案中的入口定義,增加一個resultType的參數:

@biz.Motion('demo.demo1','disp','listDemoData')
@biz.OPDescr
def op1(json):
	json.setShortcut('示範'.decode('utf-8'),'listDemoData')
	json.setParam('dispType','list').setParam('dataSource','demo.listDemoData')
	json.setParam('resultType','json')
           

這樣一來,jxTMS在查詢出資料後,就不再把每行資料先轉換為一個資料對象了,而是直接生成一個json行【就是dispAffairInfo函數的參數中的那個json】而不需要調用dispAffairInfo進行轉換,最後彙集後發送到前端。這就非常省事而且效率更高。