本文演示docker版jxTMS中简单的数据库操作,整个系列的文章请查看:docker版jxTMS使用指南
首先完成下述任务【参考前文】,以后的文章不复赘述:
-
启动tms容器
-
连接到tms的root控制台,然后启动jxTMS
-
ssh到tms,并保持查看实时日志
创建数据表
然后打开sftp,将我们下载下来的data文件,上传到tms容器中的【~/codeDefine/demo/demo1】目录下。然后执行一次热机刷新。
请注意,在启动jxTMS的root控制台,我们可以看到有日志信息输出,去除时间等信息后为:
数据表(demoData)是否存在:false
创建数据表:demoData
CREATE TABLE demoData(ID bigint NOT NULL PRIMARY KEY,NoUsed TINYINT NOT NULL,Type VARCHAR(32) NOT NULL,CreateTime DATETIME NOT NULL,Name VARCHAR(126) NOT NULL)
CREATE INDEX index_demoData_1 ON demoData (Type)
CREATE FULLTEXT INDEX index_demoData_F0 ON demoData (Name) WITH PARSER ngram
注:上述日志信息是输出到系统日志中的,而非组织的日志
即,在我们上传了data文件后,在重新加载时,jxTMS发现本组织的数据库中不存在demoData数据表,然后就自动根据我们在data文件中的定义创建了该表。
那么,请打开data文件,看看我们在其中定义了什么:
class demoData:
#jxTMS的数据对象必须有主键才能保存,一般建议使用long型的ID作为主键,否则可能会出现各种意外
field ID long primaryKey
field CreateTime datetime
field Type string len=32 index 1
field Name string len=126 fulltext
field NoUsed bool
;
然后我们看一下系统日志中的建表语句,首先是创建数据表demoData,然后还为该表创建了两个索引,一个是建立在Type字段上的普通索引,一个是建立在Name字段上的全文索引,正好对应我们在data中对demoData虚拟数据类的定义。
如果有熟悉mysql的同学,可以对照建表语句和demoData中各字段的定义,可以看出两者正好是一一对应的。然后,我们看一下mysql中是否确实创建了demoData数据表呢?执行:
#在root控制终端输入:
mysql -u root -p
#提示密码时,输入:123456
#然后在mysql>提示符后输入:
mysql> use demoOrg_2255
mysql> describe demoData;
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| ID | bigint | NO | PRI | NULL | |
| NoUsed | tinyint | NO | | NULL | |
| Type | varchar(32) | NO | MUL | NULL | |
| CreateTime | datetime | NO | | NULL | |
| Name | varchar(126) | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+-------+
5 rows in set (0.05 sec)
demoData数据表确实创建了,其各字段的定义也完全是按照我们在data文件中的定义创建的。
注:数据表创建后不可以修改其定义,即之后我们再修改data文件虚拟数据类的定义,jxTMS不会将其和数据库进行同步。这主要是出于安全的考虑:随便动一下data文件中虚拟数据类的定义,就把数据库中数据表的定义也修改了,非常容易丢失数据!
写入数据
我们修改一下capa.py文件中的sayHello函数:
@myModule.event('cmd', 'sayHello')
def sayHello(self, db, ctx):
jo = pyORM.create(db,'demoData')
jo.Type = "demo"
jo.Name = "sayHello"
db.update(jo, 'Type', 'Name');
然后保存并上传capa.py,并热机刷新。
然后点击快捷栏【演示->helloWorld】,然后点击【点我】按钮。
由于我们删除了sayHello函数中的setOutput语句和log语句,所以界面和日志中看不到任何反应,那我们看一下数据库。执行:
mysql> select * from demoData;
+------------------+--------+------+---------------------+----------+
| ID | NoUsed | Type | CreateTime | Name |
+------------------+--------+------+---------------------+----------+
| 1719331491676285 | 0 | demo | 2023-03-17 14:31:01 | sayHello |
+------------------+--------+------+---------------------+----------+
1 row in set (0.00 sec)
我们看到刚刚创建的demoData表中出现了一条数据,其Type字段正好是demo,而Name字段正好是sayHello,再看一下CreateTime字段,也正好是我们点击【点我】按钮的时间。
大家会看到,我们并没有对ID字段、CreateTime字段做任何操作,但其也得到了赋值,这是因为jxTMS会对虚拟数据表的这几个字段自动进行赋值:
-
如果存在ID字段,则生成一个唯一性ID并赋值
-
如果存在CreateTime字段,则将当前时间赋值
-
如果存在NoUsed字段,则赋值false
-
如果存在Info、Extant、FlowExec字段,则赋值一个空对象的json字符串
sayHello函数的处理逻辑比较简单,其第一条语句是创建一个demoData对象,然后对Type、Name两个属性进行赋值,最后是将对Type、Name的修改保存到数据库中。
大家回头看一下我前面凡是说到数据类,都加了一个虚拟的定语。这是什么意思呢?
简单的说,凡是在data文件中定义的数据类,都是pyORM类,在java空间也好、python空间也好,实际上并不存在一个叫做demoData的类,只有pyORM类,只不过其会伪装成我们定义的demoData类。我们对该对象的任何修改,pyORM都会拦截,当我们调用update函数时,将其保存到数据库的demoData数据表中。
注:修改了数据对象的属性,一定要在update函数的可变长参数表中罗列,否则修改不会反映到数据库中
读取数据
请再次查看mysql中【select * from demoData】的输出,记住ID的值【我的是1719331491676285,这么长大家靠记肯定容易出错,所以大家要了解一下如何自己的命令行终端是如何从控制台选择并复制数据的】。然后我们修改一下capa.py文件中的sayHello函数:
@myModule.event('cmd', 'sayHello')
def sayHello(self, db, ctx):
#要将1719331491676285改成你在上面查出来的ID值,否则会掷出Null对象异常
jo = orm.getByID(db.getDBConn(),'demoData',1719331491676285)
jx.log('type:{}',jo.Type)
jx.log('name:{}',jo.Name)
然后保存并上传capa.py,并热机刷新。
然后点击快捷栏【演示->helloWorld】,然后点击【点我】按钮。这时可以从实时日志中看到:
type:demo
name:sayHello
getByID一般用在查看详情、修改等处,ID值这种情况下都是作为参数送入的。
从web界面读取输入来设置数据对象属性
我们对web文件中的helloWorld界面进行修改:
//helloWorld的界面
web helloWorld type div;
web helloWorldt1 parent helloWorld type table title="世界,你好",width=900;
with helloWorldt1 row 0 col c0 web n type text text='类型:',width=200;
with helloWorldt1 row 0 col c1 web n bind joType type combobox width=200,useText=true,
values=[{'text':'类型甲'},{'text':'类型乙'}];
with helloWorldt1 row 0 col c2 web n type text text='名称:',width=200;
with helloWorldt1 row 0 col c3 web n bind joName type input width=300,
placeholder="请输入名称...";
with helloWorldt1 row 1 col c0 web n type button width=80,text='点我',motion=cmd,demand=sayHello,confirm='确认要执行吗!!',onlyOnce=false;
主要是修改了0行的c1列,将其类型改为下拉框,绑定的数据名改为了joType;增加了c2、c3列,是一个输入名字的输入框,数据名绑定为joName。
保存web文件,然后再修改一下capa.py文件中的sayHello函数:
@myModule.event('cmd', 'sayHello')
def sayHello(self, db, ctx):
jo = pyORM.create(db,'demoData')
#读取web输入joType
jo.Type = self.getInput('joType')
jo.Name = self.getInput('joName')
db.update(jo, 'Type', 'Name');
然后保存并上传capa.py、web,并热机刷新。
然后点击快捷栏【演示->helloWorld】,然后点击【点我】按钮。执行后,要在mysql中执行【select * from demoData】进行查看。
事件响应函数中,用self.getInput函数就可以直接读取到绑定了数据名的输入型控件中用户输入的值,相关信息可参考文末参考资料中的编程手册中的相关内容。
参考资料:
下面的系列文章讲述了如何用jxTMS开发一个实用的业务功能:
下面的系列文章讲述了jxTMS的一些基本开发能力: