前言
光阴似箭,日月如梭,转眼间2020年已经过去了一半。闲言少叙,先进行下自我介绍,我是一名合格的滴滴司机只是一个城市行者,还未达到城市英雄的地步,疫情期间,没什么收入了。只能凑合着写点代码维持生计。最近用了小半年的时间写了点东西,拿出来和大家分享下,也不知道有没有用,希望大家多给点意见,毕竟我不是外卖小哥,能力有限。
第一章:为什么要自己写东西?
-
首先:对于前端的开发人员来说,服务端,以及数据库并不是那么了解,对于mysql 建表 等等一系列操作很吃力。主要是我不会写sql。画一个前端页面可能个把小时就搞定了,写接口、写sql等等 迟迟搞不定,搞定了还容易错。
-
其次:很多单表查询或者几个表联合查询,很多时候都是复制粘贴改改字段,改改表名、每次都要写好烦,不想一味的板砖!
-
再次:写完的sql有时候还是错的,或者需求一变原来的接口基本上都不能用了
-
最后:之前没写过。想试试 node+express+typescript+ mysql
第二章:我写的东西是什么?
- 【一】模型,看图说话

1.上图的每一个小球,代表是一个model, 也可以说是对应数据库的表。
2.球和球中间的线,代表的是模型和模型的关系。实线代表的是一对多,虚线代表的是多对一,多对多通过中间模型来实现。
2.球和球中间的线,代表的是模型和模型的关系。实线代表的是一对多,虚线代表的是多对一,多对多通过中间模型来实现。

1.模型有两个维度 基本属性(数据库的字段)和关联关系。
2. 在工程启动或者初始化模型的时候,会检查数据(MYSQL),对每一个模型的基本属性 进行增删改。
2. 在工程启动或者初始化模型的时候,会检查数据(MYSQL),对每一个模型的基本属性 进行增删改。
- 【二】接口,上才艺!
export class Base extends Service {
public modelbase: Array<string>;
public base: Array<string>;
public relation: any;
public modelName: string;
constructor(public model: any) {
super();
this.modelbase = model['modelbase']
this.base = model['base']
this.relation = model['relation']
this.modelName = model['modelName']
}
@Method('/query')
query(param?: object){
....
}
@Method('/add')
add(param?: object){
....
}
@Method('/batchCascadeAdd')
batchCascadeAdd(param?: object){
....
}
...
}
export function service(): object {
return getModel().then(res => {
model = res
let service: any = {}
for (let m in model) {
let base: any = new Base(model[m])
innerService[`${m}`] = {}
for (let key in base) {
if (key.indexOf('/') > -1) {
service[`${m.toLowerCase()}${key.toLowerCase().replace(/\//g, '')}`] = function (param: any) {
return base[key].call(base, param)
}
innerService[`${m}`][`${key.replace(/\//g, '')}`] = (param: any) => {
return base[key].call(base, param)
}
}
}
}
return service
})
}
export { innerService }
1.当数据库检查完成后,会在内存中对所有模型进行初始化。
2.同时通过上述部分代码, 根据model动态的生成service
2.同时通过上述部分代码, 根据model动态的生成service
(1).add/增
(2).save/新增或者修改
(3).del/删
(4).update/改
(5).batchCascadeAdd/批量级联增加修改
(6).batchCascadeDelete/批量级联删除
(7).queryall/无限级联查询
(8).query/根据条件查响应的关系(一对多或者多对一,分页多)、条件条件查询接口
(2).save/新增或者修改
(3).del/删
(4).update/改
(5).batchCascadeAdd/批量级联增加修改
(6).batchCascadeDelete/批量级联删除
(7).queryall/无限级联查询
(8).query/根据条件查响应的关系(一对多或者多对一,分页多)、条件条件查询接口
function readFold(foldPath: string) {
fs.readdir(__dirname + foldPath, (_err, _files): void => {
if (_err) {
console.log(_err);
return
}
for (const item of _files) {
const module = require(`./modules/${item}`).default
const method: any = {}
for (let key in module) {
if (key.indexOf('/') > -1) {
method[key.toLowerCase().replace(/\//g, '')] = function (param: any) {
return module[key].call(module, param)
}
}
}
poollocal = Object.assign(method, poollocal)
}
logger.info('local API is load')
});
pool = Object.assign(poolbase, poollocal)
}

import express from 'express'
import { Adapter } from './adapter'
const router = express.Router()
router.get(/$/, Adapter)
router.post(/$/, Adapter)
export default router
遍历module 文件夹,把自动生成的接口和自己写的接口 统一放在Adapter里。这样再也不用一个一个接口去定义了。
PS: 动态模型的接口都注册确实有点性能上的浪费,动态生成有很多可能用不上,应该改成手动配置的。
- 【三】来吧,展示,结果!

上图是不带任何条件的query

上边model 部分忘记介绍了,那就在这里补上吧!
之前说过两个球之间的线 代表着关联关系 看第一张球图:
user和userGroup 多对一
userGroup和user 一对多
在查询的时候只需要 增加一个参数{path:['路径名']} 就能关联出响应的 相关模型数据
- 如:user和userGroup 多对一 结果为:
- userGroup 是object
[
{
"id": "fd87ad6fe1343c9af65353496bbb7a5a",
"createTime": "2020-06-23T08:14:37.000Z",
"updateTime": "2020-06-23T08:14:37.000Z",
"status": "status_able",
"area": "33",
"tel": "12",
"relName": "2",
"userName": "ddd ",
"userGroupId": "570ce153a1343c998c198b9e76b90a7f",
"userGroup": {
"id": "570ce153a1343c998c198b9e76b90a7f",
"createTime": "2020-06-22T01:18:15.000Z",
"updateTime": "2020-06-22T01:18:15.000Z",
"groupName": "用户组1"
}
},
{
"id": "5240b26dc1343c9af6337f1134612eb7",
"createTime": "2020-06-23T08:13:50.000Z",
"updateTime": "2020-06-23T08:13:50.000Z",
"status": "status_disable",
"area": "d",
"tel": "128390",
"relName": "阿圣诞节快乐",
"userName": "张三1",
"userGroupId": "e53f136231343c99a060770d6ea4bb67",
"userGroup": {
"id": "e53f136231343c99a060770d6ea4bb67",
"createTime": "2020-06-22T02:51:04.000Z",
"updateTime": "2020-06-22T02:51:04.000Z",
"groupName": "www"
}
}
]

- 如:userGroup和user多对一 结果为:
- userGroup 是 数组
[
{
"id": "e53f136231343c99a060770d6ea4bb67",
"createTime": "2020-06-22T02:51:04.000Z",
"updateTime": "2020-06-22T02:51:04.000Z",
"groupName": "www",
"user": [
{
"id": "5240b26dc1343c9af6337f1134612eb7",
"createTime": "2020-06-23T08:13:50.000Z",
"updateTime": "2020-06-23T08:13:50.000Z",
"status": "status_disable",
"area": "d",
"tel": "128390",
"relName": "阿圣诞节快乐",
"userName": "张三1",
"userGroupId": "e53f136231343c99a060770d6ea4bb67"
}
]
},
{
"id": "570ce153a1343c998c198b9e76b90a7f",
"createTime": "2020-06-22T01:18:15.000Z",
"updateTime": "2020-06-22T01:18:15.000Z",
"groupName": "用户组1",
"user": [
{
"id": "fd87ad6fe1343c9af65353496bbb7a5a",
"createTime": "2020-06-23T08:14:37.000Z",
"updateTime": "2020-06-23T08:14:37.000Z",
"status": "status_able",
"area": "33",
"tel": "12",
"relName": "2",
"userName": "ddd ",
"userGroupId": "570ce153a1343c998c198b9e76b90a7f"
}
]
}
]
第三章:代码放哪里了?
重点来了!!!
重点来了!!!
重点来了!!!
Github:star直通车
