数据库记录插入功能
本篇文章我们将介绍如何使用ADI平台定义一个向目标数据库插入记录的接口,包括手工组装报文单表插入、手工组装报文多表插入、自动组装报文多表插入三种方式。无论是单表插入还是多表插入,任何一条记录写入失败,那么默认情况下API平台的整个数据插入事务都将自动回滚。
通过本API平台,可以快速实现直接写入数据到目标数据库,常见于大数据局等单位提供一个数据库连接方式,然后要求各业务系统自行把数据写入该数据库,以实现数据归集的需求,俗称数据同步。根据restful规范,API平台的POST接口可快速实现该功能。
值得注意的是,在数据同步场景中,当多个数据库表之间存在外键关联时,目标库几乎不会使用自增主键作为其它表的外键值,而是会使用具有唯一性的字符串作为外键关联,因为使用自增字段值的话,是无法保证源库和目标库的主键值一致性的。
1.需求说明
根据前续文章的例子,我们已经有一个网签备案系统,数据库名为business_system,里面有幢数据、户数据、交易者数据。假设现在市数据局提供了一个他们的数据库名为dsj(大数据的缩写),并要求我们实时归集幢数据和户数据到该数据库对应的表中。
dsj数据库的幢表名为dsj_zhuangs,建表语句如下:
create table dsj_zhuangs
(
xh bigint(20) not null primary key auto_increment comment '幢序号',
zhdjdydm varchar(50) not null comment '幢登记单元代码',
zl varchar(100) comment '幢坐落'
);
alter table dsj_zhuangs add unique (zhdjdydm);
dsj数据库的户表名为dsj_hus,建表语句如下:
create table dsj_hus
(
xh bigint(20) not null primary key auto_increment comment '户序号',
hdjdydm varchar(50) not null comment '户登记单元代码',
zhdjdydm varchar(50) not null comment '所属幢登记单元代码',
fbm varchar(50) comment '房编码',
qsc int(4) comment '起始层',
zhzhc int(4) comment '终止层',
fh varchar(50) comment '室号/部位',
zl varchar(100) comment '房屋坐落',
jzjg varchar(50) comment '建筑结构',
ghyt varchar(50) comment '规划用途',
jzmj double(18, 3) comment '建筑面积'
);
alter table dsj_hus add unique (hdjdydm);
-- 设置户表的外键:zhdjdydm
alter table dsj_hus add constraint hus_fk_zhdjdydm foreign key (zhdjdydm) references dsj_zhuangs(zhdjdydm);
接下来我们将分别使用手工组装报文单表插入、手工组装报文多表插入、自动组装报文多表插入三种方式实现该需求(注:这三种方式都不包括改造业务系统以连接目标库来写入数据,因为这样对咱们业务系统的侵入性太大,耦合度太高;我们要通过API平台实现数据插入)。
在此之前,我们需要先在API平台定义一个OAuth客户端,系统名称可以就叫"大数据平台",具体定义过程可以参考之前的文章,这里不再赘述。如图:
2.手工组装报文单表插入
所谓手工组装报文,即改造我们的业务系统,通过程序组装json报文,然后调用API平台的接口来完成数据插入。
2.1 实现对dsj_zhuangs表的插入
要通过API平台插入数据到数据库表,那么json报文的根节点必须有一个和表名相同的节点名称,即dsj_zhuangs(大小写不敏感),报文结构如下:
{
"dsj_zhuangs": [{
"zhdjdydm": "幢登记单元代码/不动产单元号",
"zl": "幢坐落"
}]
}
dsj_zhuangs节点可以是一个json对象(意味着只能单条数据插入)或者是一个json数组(意味着可以多条数据插入),每个json对象的属性值必须和数据库表的字段名相同(大小写不敏感)。
2.1.1 在API平台定义一个POST路由
路由编码可定义为insertZhuang2dsj,意思是插入幢数据到大数据平台。如图:
注意调用方式选择post。
2.1.2 在路由下定义一个分享设置
在分享设置中填写大数据平台的数据库(即目标库)连接方式。如图:
注意这里要填写目标数据库的连接方式。保存后可以测试数据库是否可以连接,如图:
2.1.3 在分享设置中定义目标库的数据库表
点击分享设置后面的[表定义]。如图:
在表定义界面点击[新增],填写以下字段,如图:
核心字段说明:
表名: 是指要操作的目标数据库表名称(大小写不敏感)。
中文名: 是指数据库表的中文名称,实事求是即可。
主键字段: 是指该数据库表的主键字段名,非必填;。
序列名: 是指用于生成该数据库表的主键值的序列非必填;一般Oracle或PostgreSql数据库才会用到。
写入顺序: 当需要写入多个表时,用来控制当前表的写入顺序,值越小表示越需要优先写入,比如父表需要优先于子表写入;这里只有一张表,使用默认值10即可。
写入条件JS: 当JS返回true时,表示需要写入该表,否则不写入;具体应用场景会在后续文章介绍。
填写完成后点击保存即可,API平台会自动解析该表的字段类型和是否可空等属性。如图:
点击[字段信息],如图:
这里的字段信息默认是该表的所有字段,同时意味着接口调用者可以发送这些字段,如果我们不想由接口调用者传入自增主键的值,那么应该在这里把"xh"字段删除。
2.1.4 调用接口完成幢表数据插入
打开在线接口文档,如图所示:
我们填写以下json数据:
{
"dsj_zhuangs": [{
"zhdjdydm": "110108001001GB00001F0001",
"zl": "北京市海淀区曙光中路曙光花园智业园1幢"
},
{
"zhdjdydm": "110108001001GB00001F0002",
"zl": "北京市海淀区曙光中路曙光花园智业园2幢"
}
]
}
点击[试一下],如图所示:
可以看到接口调用成功了,再看看dsj库里是否有数据了:
幢数据被成功写入。
2.2 实现对dsj_hus表的插入
根据上述内容不难看出,我们需要一个新的路由,按照同样的流程进行定义,在表定义功能中定义dsj_hus表即可,目标库的配置都是一模一样的,既然这样,我们可以使用API平台的路由复制功能,复制一个路由出来进行修改即可。
2.2.1 在API平台复制一个POST路由
在路由设置列表页面选择我们要复制的路由,点击[复制]按钮,如图所示:
然后点击[开始复制]即可复制成功:
2.2.2 在分享设置中定义目标库的数据库表dsj_hus
通过路由复制功能,我们可以完全把源路由的分享设置、数据定义、表定义复制到新路由上。接下来,我们到新路由中删除原来的表定义(dsj_zhuangs),添加新的表定义(dsj_hus)即可。如图:
2.2.3 调用接口完成户表数据插入
打开在线接口文档,如图所示:
我们填写以下json数据:
{
"dsj_hus": {
"hdjdydm": "110108001001GB00001F00010003",
"zhdjdydm": "110108001001GB00001F0001",
"fbm": "fbm0003",
"qsc": 1,
"zhzhc": 1,
"fh": "103",
"zl": "北京市海淀区曙光中路曙光花园智业园1幢B座1-103",
"jzjg": "钢结构",
"ghyt": "住宅",
"jzmj": 183.00
}
}
点击[试一下],如图所示:
可以看到接口调用成功了,再看看dsj库里是否有数据了:
户数据被成功写入。
3.手工组装报文多表插入
3.1 在API平台复制一个POST路由
单表插入大家已经明白如何实现了,要实现多表插入,同样很简单,只需要在表定义的时候把这些表都定义进去即可。
我们还是复制一个路由(insertHu2dsj),填写新的路由编码和路由名称。如图:
3.2 在分享设置中定义目标库的数据库表dsj_zhuangs
复制之后已经有dsj_hus的表定义了,我们追加dsj_zhuangs的表定义即可,同时修改dsj_zhuangs的写入顺序要小于dsj_hus的写入顺序(即写库的时候要先写幢表,再写户表)。如图:
3.3 调用接口完成幢表和户表数据插入
打开在线接口文档,如图所示:
我们填写以下json数据:
{
"dsj_zhuangs": [{
"zhdjdydm": "110108001001GB00001F0001",
"zl": "北京市海淀区曙光中路曙光花园智业园1幢"
},
{
"zhdjdydm": "110108001001GB00001F0002",
"zl": "北京市海淀区曙光中路曙光花园智业园2幢"
}
],
"dsj_hus": {
"hdjdydm": "110108001001GB00001F00010003",
"zhdjdydm": "110108001001GB00001F0001",
"fbm": "fbm0003",
"qsc": 1,
"zhzhc": 1,
"fh": "103",
"zl": "北京市海淀区曙光中路曙光花园智业园1幢B座1-103",
"jzjg": "钢结构",
"ghyt": "住宅",
"jzmj": 183.00
}
}
首先我们清空dsj库中之前已经写入的数据(否则唯一键冲突接口会报错),然后点击[试一下],如图所示:
可以看到接口调用成功了,再看看dsj库里是否有数据了:
幢表:
户表:
两个表的数据都被成功写入。
4.自动组装报文多表插入
所谓自动组装报文,就是通过API平台的数据查询功能组装出约定的json报文格式,再把报文转发给另一个路由。这里会引出API平台的一个新功能,即请求转发,下面让我们看看如何实现。
思路: 定义一个路由,该路由接收一个或多个幢不动产单元号,然后编写sql查询这些不动产单元号对应的幢数据和户数据,最终把查询到数据转发到我们刚才定义的insert2dsj路由上,完成数据插入。
这么做的好处是什么? 减轻了业务系统组装报文的工作量,业务系统只需要传入极少的参数(幢不动产单元号)即可完成数据同步。
4.1 在API平台定义一个GET路由
如果以前定义过类似的查询接口,那么我们可以使用路由复制功能;不管是复制还是从头定义,这里都不再赘述(但是我要偷偷的告诉你:为了适应不同系统的对接需求,API平台的POST路由其实也能查库,从请求的json中获取查询条件而已,原理是一样的),下面展示一些关键页面的截图。
get路由:
4.2 在GET路由下新增一个分享设置
可以看到这个分享设置既需要连数据库(用来查询数据组装报文),还需要转发到另一个接口(我们前面定义的insert2dsj),由于是ADI平台自己转发给自己的接口,因此目标系统建议选择"adi"。
4.3 在分享设置下定义sql
同样的,我们需要按照数据写入的标准查询得到以下json报文格式:
{
"dsj_zhuangs": [{
"zhdjdydm": "110108001001GB00001F0001",
"zl": "北京市海淀区曙光中路曙光花园智业园1幢"
},
{
"zhdjdydm": "110108001001GB00001F0002",
"zl": "北京市海淀区曙光中路曙光花园智业园2幢"
}
],
"dsj_hus": [{
"hdjdydm": "110108001001GB00001F00010003",
"zhdjdydm": "110108001001GB00001F0001",
"fbm": "fbm0003",
"qsc": 1,
"zhzhc": 1,
"fh": "103",
"zl": "北京市海淀区曙光中路曙光花园智业园1幢B座1-103",
"jzjg": "钢结构",
"ghyt": "住宅",
"jzmj": 183.00
}]
}
也就是定义两条sql语句,分别如下:
查询幢数据的sql:
select z.ZHDJDYDM,z.ZL from zhuang z where z.ZHDJDYDM in (request~zhdjdydms~)
因为我们要支持同时插入多个幢,因此这里使用in查询。
查询户数据的sql:
SELECT
h.HDJDYDM,
z.ZHDJDYDM,
h.FBM,
h.QSC,
h.ZHZHC,
h.FH,
h.ZL,
h.JZJG,
h.GHYT,
h.JZMJ
FROM
h
JOIN zhuang z ON h.ZXH = z.ZXH
AND z.ZHDJDYDM IN (request ~zhdjdydms~)
sql定义完成后如图所示:
4.4 调用接口完成幢表和户表数据插入
首先我们清空dsj库中之前已经写入的数据(否则唯一键冲突接口会报错)。打开在线接口文档,如图所示:
入参填写两个幢的幢登记单元代码(用中括号把多个值括号来以实现in查询的多个入参):[“110108001001GB00001F0001”,“110108001001GB00001F0002”],
然后点击[试一下],如图所示:
哎呀,怎么报错了?
这是因为如果在分享设置中配置了请求转发到目标接口,那么就必须告诉API平台如何判断目标接口是否调用成功,因此,我们需要在分享设置的扩展配置中填写以下内容:
{
"statenode": "type",
"successvalue": "success",
"datanode": "data",
"errornode": "data"
}
扩展配置接收的是一个json对象,用于无限扩展API平台的功能,在扩展配置中还有很多其它可配置的功能,今后会一一介绍。这几个字段的含义:
statenode: 第三方接口响应json中标识本次调用成功与否字段的key值(多层使用 “.” 隔开),和succcessvalue搭配使用;如果没有明确字段用来标识成功与否,则无需配置;按照咱们API平台的响应规范,因此这里值为"type"。
successvalue: 第三方接口响应json中标识成功与否字段的value值(多个值用“,”隔开,例如200和201都表示成功);如果没有配置statenode,则无需配置succcessvalue;按照咱们API平台的响应规范,因此这里值为"success"。
datanode: 请求转发时必须配置,判断第三方返回成功后,从哪个json节点取对应的业务数据(多层使用 “.” 隔开);注:当值配置为bitWholeBody的时候,表示把第三方的整个响应body作为业务数据(一般不会配置为bitWholeBody);按照咱们API平台的响应规范,因此这里值为"data"。
errornode: 请求转发时必须配置,当判定第三方接口调用失败后,API平台也会响应失败,失败提示信息为第三方的失败信息(多层使用 “.” 隔开);按照咱们API平台的响应规范,因此这里值为"data"。
总结起来描述就是: API平台通过目标接口响应的statenode节点值获取目标接口的响应状态,当statenode节点值在successvalue节点值之中时,认定本次调用成功,然后从datanode节点取出目标接口响应的业务数据,否则认定本次调用失败,然后从errornode节点取出目标接口响应的失败原因。如果没有配置statenode(例如百度云的接口可能没有明确的字段告诉我们成功与否),那么当errornode节点有值时,就认为目标接口调用失败。
我们把扩展配置加上,如图所示:
保存后,回到刚才的在线接口文档页面,再此点击“试一下”,如图所示:
可以看到接口调用成功了,再看看dsj库里是否有数据了:
幢表:
户表:
两个表的数据都被成功写入。
5.查询接口调用日志
通过日志查询,我们能清晰的看到两个接口的日志详情。
接口queryData4dsj的日志:
接口queryData4dsj的日志:
到这里,通过API平台实现数据库记录插入的几种方式就讲完啦,后续我将继续介绍ADI平台其它的重要功能,谢谢大家的阅读!