自定义数据类
jxTMS提供了自定义数据类的能力,通过在data文件中自定义数据类,可以:
- 在python代码中直接用jxTMS提供的函数创建该数据类的对象,并象普通对象那样访问自己定义的该对象的属性
- 在包含该数据类定义的模块被加载到组织中时,jxTMS会在该组织的私有数据库中检查是否存在同名数据表,如果没有则根据该数据类的定义自动创建同名数据表
注1:jxTMS不支持动态修改数据表定义,但jxTMS支持类表同步的数据类继承。如果开发者需要修改数据表,建议不要去修改数据表,而是直接继承原来的数据类,然后在这个子类中定义新的属性,jxTMS会为这个新定义的子类生成相应的数据表,同时自动关联原数据表,使得该子类既拥有原数据类的一切属性,也拥有新增加的数据属性
注2:如果开发者熟悉mysql操作,自然也可以按后文java数据类型和mysql数据类型的映射,直接修改数据表定义,然后在data文件修改数据类定义,然后热机刷新一下即可正常使用了。但开发者应确保新增加的列允许null数据,同时自行处理相应的业务逻辑兼容性。这也笔者不建议直接修改数据表定义的原因:需要开发者非常熟悉mysql同时具备仔细调整业务逻辑使之同时兼容调整前后数据的能力。而用类表同步来继承的方式则无这些麻烦
- 利用jxTMS所提供函数可以保存该对象到组织的私有数据库中的同名数据表中
- 利用前文的数据源,可以从数据库中的同名数据表中读取之前保存的数据
- 利用jxTMS所提供函数可以直接从同名数据表中读取符合条件的数据并生成一个该类的数据对象,然后将读到的数据赋值给该对象
data文件中的数据类定义语法如下:
class 数据类名 (super 父类名)? :
field 属性名1 数据类型 长度? 键? 标志? 约束?
field 属性名2 数据类型 长度? 键? 标志? 约束?
......
索引定义*
;
再次强调:所有jxTMS的定义语法都参考了java中正则表达式的定义,如果开发者不太熟悉正则表达式的定义,请先仔细阅读与理解java等语言中的正则表达式的定义。上面的?代表可选,即出现0次或1次;*代表可选重复,即出现0次或多次。
数据类名最好不要用中文,同时在一个组织内不得重复,因为其会映射到本组织的私有数据库中为同名数据表。super指出本类是继承自哪个已经定义过的父类【当然也必须是orm数据类】,该父类可以是jxTMS内嵌的数据类,当然最好是开发者自己定义的数据类,但必须在本类之前先行定义。jxTMS没有限制继承层数,也就是说,父类也可以是继承自其它数据类的子类,jxTMS会自动完成所有父类及本类对应的数据表的关联。
注1:类的继承在数据表关联时,jxTMS默认这些父子数据表是通过长整数型的ID字段进行级联的
注2:虽然jxTMS不限制继承的层数,但子类在查询时是需要级联父数据表的,而当前的关系数据库的数据表级联都是以笛卡尔乘积的方式进行的,如果级联的数据表太多,则查询速度会比较慢,所以开发者还是应谨慎控制继承层数,以避免影响数据库查询速度
其后的每一行field定义就是定义了数据对象的一个属性,也是同名数据表中的一列。
数据类型
目前支持的数据类型包括:
- int:整数,对应java中的int类型、myslq中的INTEGER类型
- float:浮点数,对应java中的double类型、myslq中的DOUBLE类型
- string:字符串,对应java中的string类型、myslq中的MEDIUMTEXT或varchar类型
- bool:布尔变量,对应java中的boolean类型、myslq中的TINYINT类型
- datetime:日期,对应java中的Date类型、myslq中的DATETIME类型
- long:长整数,对应java中的long类型、myslq中的bigint类型
- json:json类型,对应到java中是jxTMS内嵌的jxJson类型、myslq中的MEDIUMTEXT类型
- bigDecimal:高精度浮点数,对应java中的BigDecimal类型、myslq中的DECIMAL类型
jxTMS会自动完成在保存数据到数据库时将java类型转换为相应的转换,如将boolean的true转换为1;在读取数据并生成orm数据对象时,自动将mysql数据库中的数据转换为java类型,如将1转换为true,将字符串转换为jxJson等。
长度
长度是可选定义项,其定义语法如下:
len = 整数的数字
目前只有string和bigDecimal两类型的字段需要定义长度:
- string类型字段如果没有定义长度,则数据库类型为MEDIUMTEXT,即最大可大16777215 个字节;而如果定义了长度,则为该长度的VARCHAR,由于汉字为双字节,所以长度最好小于127
- bigDecimal类型如果没有定义长度,则精度是24,小数点后6位;而如果定义了长度,则精度是24,小数点后位数即为这里定义的长度
键
指示本字段是否定义为键,目前共有三种键的定义:
主键:
primaryKey
说明:一个数据类必须定义primaryKey【无主键则无法提交update】,可以有多个字段为primaryKey,即同名数据表的主键就是由这些字段共同组成的,一般这种情况只有关系才会出现
一般的实体对象只应该定义一个primaryKey,而且最好是long型的ID,如demo中的order:
field ID long primaryKey
索引:
index 整数的数字
说明:定义一个索引,如果有多个列的索引号相同,则该索引是这些列共同组成的复合索引
全文索引:
fulltext
说明:定义一个本列的全文索引,由于在定义查询条件时,无法判断数据库是否定义了全文索引,更不知道全文索引到底由哪些列组成,所以jxTMS强制所有的全文索引是单列的。而由于mysql一个查询语句只能引用一个全文索引,所以请务必不要在定义数据源时使用多个全文索引,否则无法查询到任何数据
标志
指示本字段是一个标志位,即其只能由指定的值组成,该字段只能是int类型,其定义语法如下:
field 属性名 int flag=[字符串数组]
例:
field Right int flag=['读','写','执行']
说明:
Right=1,即意为读
Right=6,即意为写+执行
即读是1、写是2、执行是4,Right可以是这三个数字的或组合,0就是没有任何权限
代码示例:
#python中的字符串编码和java中的编码不一致,如果是中文,必须按如下形式先转码,这也是笔者反复强调变量名之类的尽量少用中文的原因
jo.Right='读'.decode('utf-8')
#如果有多个值则用英文逗号分隔
jo.Right='写,执行'.decode('utf-8')
约束
指示本字段取值受约束,即其只能是指定的值,该字段只能是string类型,其定义语法如下:
field 属性名 string restraint=[字符串数组]
例:
field State string restraint=['运行中','暂停','取消']
说明:
State的取值就只能是约束所指定的这三个值之一,否则掷出异常
代码示例:
jo.State='运行中'.decode('utf-8')
jo.State='取消'.decode('utf-8')
#异常
jo.State='结束'.decode('utf-8')
索引
由于每个字段只能有一次键的定义,所以当某字段被多个索引使用到时,就应手工定义索引。其语法如下:
index 索引名 字段名 (, 字段名)+
说明:+的意思是出现一次或多次
例:
index testIndex Right,State
类表同步
类表同步是指jxTMS的数据类支持继承。这样,当业务有调整时,不必修改原数据表结构,而是直接继承一个子类然后为子类定义新的字段就好。
重要的是:用新的业务处理函数来处理新的数据类,而之前的业务逻辑不需要任何修改
而jxTMS会自动将子类的同名数据表和父类的同名数据表以ID相等为条件进行关联,相关的java空间、python空间、自动生成的数据库的select语句、insert语句、update语句jxTMS全部做了相应的处理以确保数据库中的数据和python代码空间中的数据对象相一致。这种能力即是类表同步。
为了正确应用这一能力,自定义的数据类【包括父类、子类】,必须以long型的ID为primaryKey,否则无法正确关联,也就无法实现类表同步的继承了。
为便于大家理解,demo的order模块中定义了salesOrder数据类,同时还定义了extOrder子类,大家可阅读该data文件,然后对照数据库中的salesOrder、extOrder两表就容易理解了。
新建数据对象
当需要创建一个自定义数据类的对象时,可使用jxTMS内置的函数:
jo=pyORM.create(db,数据类名)
说明:
db是jxTMS送入的数据库操作
数据类名即是希望创建的对象的类名,如extOrder
pyORM在capa.py开头所引用的倒包语句中导入的所有自定义数据类的父类。create函数所创建的数据对象,在事件执行完毕后,会由db对象自动执行一个insert语句,并予以提交。一般来说,一个实体数据类,开发者最好默认有如下的定义:
field ID long primaryKey
field CreateTime datetime
field NoUsed bool
field Info json
field Extant json
field FlowExec json
其中,如果该数据类不需要启动审批之类的流程,则可略去Extant和FlowExec两项。则在创建后,pyORM会自动为ID、CreateTime、Info、Extant执行初始化:
- ID初始化为一个本机唯一长整数
- CreateTime初始化为当前时间
- Info初始化为空json串:{}
- Extant如果存在则初始化为空json串:{}
用户可自行对NoUsed和FlowExec进行初始化:
jo.NoUsed=False
jo.FlowExec=jxJson.getObjectNode()
读取数据对象
一般来说,数据对象有两个读取场景:
- 列表,主要通过上篇的数据源的方式读取,本文不复赘述
- 详情,则主要通过jxTMS的内置函数读取
读取一个数据对象,一般需要知道两个信息:数据类名和数据对象ID。一般来说,在处理点是明确会知道要处理什么类型的对象的,数据对象ID则通过列表中的点击时将该参数传入。当知道了这两个参数后,我们执行:
jo=pyORM.getByID(db.getDBConn(),数据类名,数据对象ID)
例:
jo=pyORM.getByID(db.getDBConn(),'extOrder',123456789)
jxTMS会自动生成一个sql语句【标准sql语句】交mysql执行:
select ta.*,tp.*
from extOrder as ta,salesOrder as tp
where ta.ID=tp.ID and ta.ID=123456789
然后根据查询出来的数据创建一个extOrder对象,然后为其一一赋值,仔细观察该语句,大家就会发现,这个extOrder是包含了salesOrder中的数据的,这就是类表同步。
修改数据对象的属性
当需要修改一个自定义数据类的对象时,可使用jxTMS内置的函数update:
jo.Number=789
jo.Amount=123.456
db.update(jo,'Number','Amount')
修改了哪几个属性,就需要在update函数中一一列出,否则不会更新到数据库中。在事件执行完毕,这些修改会被提交到数据库中。