零代码第一步,做个添加数据的服务先。node.js + mysql
2019-04-08 21:34 金色海洋(jyk) 阅读(645) 评论(0) 编辑 收藏 举报node.js + mysql 实现数据添加的功能。万事基于服务!
增删改查之添加数据。
优点:只需要设置一个json文件,就可以实现基本的添加功能,可以视为是零代码。
添加数据的服务实现的功能:
1、 添加一条记录、多条记录(批量添加)、主从表记录
2、 记录访问日志
3、 记录数据变化记录
4、 执行步骤跟踪和计时
5、 异常日志
6、 权限判断
步骤:
1、 数据库设计、建表这类的直接略过,假设有了一张表,我们要往这个表里面添加数据
2、 根据要添加的字段,设置一个json文件,对服务进行描述,并且给这个服务设置一个变化,作为区分。
3、 客户端提交数据和服务变化。
4、 服务器端,获取数据和服务变化,调用对应的程序进行处理。
5、 处理完毕后处理返回给客户的信息
6、 如果有特殊业务需求,可以用插件的方式来实现。
7、 完成
第一步,不管用什么方式做项目,都是要做的。
第二步需要弄一个json文件,这个可以自动生成,不用手写
第三步相当于做一个路由,路由规则制定好了就不用再写代码了。
第四步由框架完成,不需要写代码
第五步判断一下是否成功,按照规则给浏览器返回数据,也不用一遍一遍写。
第六步不是必须的,大部分的增删改查都是不需要插件的。
所以,基本上做一个json文件,就可以搞定一个服务。需要写的代码无限接近零代码。而json文件又可以自动生成。
下面是json文件的例子:(这个可以自动生成)
{ "operationMode":"add", "pluginBefore":"", "pluginAfter":"", "tableInfo":{ "tableName": "node_user", "primaryKey":"id", "sql": "INSERT INTO node_user(id,name,age) VALUES(0,?,?)" , "sqlSelect": "SELECT * FROM node_user WHERE id = ?" , "column":["name","age"] } }
然后再说一下代码类型,可以分为两类——框架类和项目类。
像.net框架、ado.net、express这类,内部的实现代码都是属于框架级的,内部有再多的代码,也不应该算到项目里面。
而调用类库、使用框架实现项目的代码,才是项目级的代码,才算作代码量。
这个要先说清楚,然后再发后面的代码。
http的使用,属于项目级的,http的内部实现,就是框架级的。
同理,添加服务的调用部分属于项目级的,服务内部的实现代码属于框架级的。
先不上http了,写一个简单的测试用代码,优点是不用打开浏览器就可以进行测试。要不然每次都要打开浏览器,太麻烦了。
这个不是正式的代码,仅仅是初期测试用的。这个是项目级别的代码。
/** * Created by jyk00 on 2019/3/31. * curd的服务 */ //测试添加服务 //精确计时 var time = require('../preciseTime').time; //创建添加服务对象 var service = require('./serviceAdd'); var trace={ title:'收到一个请求:100', msg:'', startTime:time(), endTime:0, useTime:0, items:[] }; service.start(100,trace,function (err,info) { msg.endTime = time(); msg.useTime = time() - msg.startTime; console.log('完成服务:'+JSON.stringify(trace)); });
添加服务的代码(业务层) 框架级代码
/** * Created by jyk00 on 2019/3/31. * 添加数据的服务 */ exports.start = function(code,trace,callback) { //精确计时 var time = require('../preciseTime').time; var traceAdd = { title:'开始添加数据的服务', msg:'', startTime:time(), endTime:0, useTime:0, items:[] }; trace.items.push(traceAdd); /** 根据配置信息实现添加数据的功能 * 获取服务信息 * 接收数据 * 验证数据 * 调用插件 * 持久化 * 获取持久化后数据 * 写数据变化日志 * 返回结果 */ //获取服务信息 //console.log('服务ID:' + code); var meta = require('./service_'+ code +'.json'); console.log('获取服务信息:' + meta); //获取实体类,先模拟一下 var data = require('./node_user.json'); var info={ trace:traceAdd, requestId:0, serviceId:code, data:data, table:meta.tableInfo }; //验证数据,暂时略 //调用持久化前的插件 var plugName = meta.pluginBefore; if (plugName.length === 0){ //没有插件,不调用 console.log('没有插件,不调用'); //持久化及后续 saveAndLast(data); } else { //有插件 console.log('有插件,调用'); var plug = require('../plugin/' + plugName); plug.begin(data,function(data){ //持久化及后续 saveAndLast(data); }); } //持久化以及之后的事情 function saveAndLast(data) { //持久化之添加数据 var db = require('./dataBaseAdd'); //持久化 db.query(info,function(err, result){ console.log('saveData的回调:' ); console.log('result:',result); //调用持久化之后的插件 plugName = meta.pluginAfter; if (plugName.length === 0){ //没有插件,不调用 } else{ //有插件 plug = require('../plugin/' + plugName); plug.begin(err, result,data,function() { }); } }); } };
持久化的代码(数据层) 框架级代码
/** * Created by jyk00 on 2019/4/1. * 数据服务之添加操作 */ //持久化内部的跟踪 var traceStartAddData = {}; //捕捉异常 process.on('uncaughtException', function (err) { console.log('uncaughtException的trace:' +JSON.stringify(traceStartAddData)); console.log("捕捉到异常啦"); console.log(err); }); exports.query = function(info,callback) { //精确计时 var time = require('../preciseTime').time; //持久化之添加数据 traceStartAddData = { title:'持久化之添加数据', msg:'', startTime:time(), endTime:0, useTime:0, items:[] }; info.trace.items.push(traceStartAddData); /** 根据配置信息实现添加数据的功能 * 获取表信息 * 接收传入的数据,验证任务由上层搞定 * 持久化 * 获取持久化后数据 * 写数据变化日志 * 返回结果 */ //==================获取表信息和数据================================= var traceGetInfo = { title:'获取表信息和数据、定义dataChange', msg:'', startTime:time(), endTime:0, useTime:0, items:[] }; traceStartAddData.items.push(traceGetInfo); //获取表信息 var tableInfo = info.table; //获取实体类 var data = info.data; //记录数据变化情况 var dataChange = { requestId:info.requestId, serviceId:info.serviceId, tableID:info.table.tableId, dataID:0, oldDataJson:'', newDataJson:'', submitDataJson:JSON.stringify(info.data), dbResult:'', trace:JSON.stringify(info.trace), addUserid:1 }; traceGetInfo.endTime = time(); traceGetInfo.useTime = time() - traceGetInfo.startTime; //==================创建MySql对象================================= var traceCreateMySql = { title:'创建MySql对象、cnString、connection', msg:'', startTime:time(), endTime:0, useTime:0, items:[] }; traceStartAddData.items.push(traceCreateMySql); //创建mysql对象 var mysql = require('mysql'); var cnString = require('../sqlConnection.json'); var connection = mysql.createConnection(cnString); traceCreateMySql.endTime = time(); traceCreateMySql.useTime = time() - traceCreateMySql.startTime; //==================发送持久化请求================================= var traceAddNewData = { title:'准备发送持久化请求,添加一条数据', msg:'', startTime:time(), endTime:0, useTime:0, items:[] }; traceStartAddData.items.push(traceAddNewData); var sql = tableInfo.sql; //数据转换成数组 var valuesParams = createParams(tableInfo,data); myQuery(sql,valuesParams,traceAddNewData,function (err, result) { //数据添加完成后的回调 //console.log('持久化的回调的trace:' +JSON.stringify(traceStartAddData)); if(err){ console.log('[INSERT ERROR ] - ',err.message); traceAddNewData.msg += '_err:' + JSON.stringify(err); callback(err, result); return; } //记录数据变化记录, var log = require('./serviceAdd_11.json'); //记录添加数据后的返回信息 dataChange.dbResult = JSON.stringify(result); //从数据库里获取刚添加的数据 var traceGetNewData = { title:'获取数据库里添加完成的数据', msg:'', startTime:time(), endTime:0, useTime:0, items:[] }; traceAddNewData.items.push(traceGetNewData); myQuery(tableInfo.sqlSelect,[result.insertId],traceGetNewData,function (err, result) { //获取一条记录完毕 //console.log('获取更新数据的回调result:' +JSON.stringify(result)); //console.log('获取更新数据的回调的trace:' +JSON.stringify(traceStartAddData)); //记录数据变化日志 var traceAddlog = { title:'记录数据变化日志', msg:'', startTime:time(), endTime:0, useTime:0, items:[] }; traceGetNewData.items.push(traceAddlog); //数据库里的新数据 dataChange.newDataJson = JSON.stringify(result); //目前为止的跟踪记录 dataChange.trace = JSON.stringify(info.trace); valuesParams = createParams(log.tableInfo,dataChange); //提交操作 myQuery(log.tableInfo.sql,valuesParams,traceAddlog,function (err, result){ //数据变化日志回调完毕 console.log('数据变化日志回调完毕:' +JSON.stringify(info.trace)); }); }); connection.end(); //回调,不等数据变化的日志了 callback(err, result); }); //console.log('调用结束等待结果'); //封装数据库操作,以及计时器 function myQuery(sql,vParme,traces,callback) { //console.log('myQuery的sql:' +sql); traces.msg += 'sql:'+sql; traces.msg += '_values:' + valuesParams; var conn = mysql.createConnection(cnString); conn.connect(); conn.query(sql,vParme,function (err, result) { //console.log('myQuery的回调:' +err); traceStart.endTime = time(); traceStart.useTime = time() - traceStart.startTime; if(err){ console.log('[ERROR ] - ',err.message); traceStart.title += '——执行出错:'+ err.message; traceStart.error = JSON.stringify(err) callback(err, result); return; } traceStart.title += '——成功!'; callback(err, result); }); conn.end(); //请求发送完毕 //console.log('请求发送完毕:'); traces.endTime = time(); traces.useTime = time() - traces.startTime; //记录完成开始时间 var traceStart = { title:'请求发送完毕,等待反馈', startTime:time(), endTime:0, useTime:0, items:[] }; traces.items.push(traceStart); } //拼接valuesParams function createParams(colInfo,data){ //console.log('开始拼接数据数组'); var valuesParams = []; //数据变成数组的形式 var colName = ""; for (var i=0 ;i<colInfo.column.length;i++) { colName = colInfo.column[i]; valuesParams.push(data[colName]); } return valuesParams; } //拼接sql function createSql2(){ sql = 'INSERT INTO ' +meta.tableName ; var cols = "(" + meta.primaryKey; var values = " VALUES(0"; var valuesParams = []; //拼接字段名和参数 for (var key in meta.cols) { cols += ',' + key; values += ',?'; valuesParams.push(meta.cols[key]); } sql +=cols + ')' + values + ')'; console.log(sql); } };
跟踪记录
{ "title": "开始添加数据的服务", "msg": "", "startTime": 2950080457.323715, "endTime": 0, "useTime": 0, "items": [{ "title": "持久化之添加数据", "msg": "", "startTime": 2950080463.596571, "endTime": 0, "useTime": 0, "items": [{ "title": "获取表信息和数据、定义dataChange", "msg": "", "startTime": 2950080463.608944, "endTime": 2950080463.683611, "useTime": 0.08490705490112305, "items": [] }, { "title": "创建MySql对象、cnString、connection", "msg": "", "startTime": 2950080463.702811, "endTime": 2950080586.696783, "useTime": 122.99781227111816, "items": [] }, { "title": "准备发送持久化请求,添加一条数据", "msg": "sql:INSERT INTO node_user(id,name,age) VALUES(0,?,?)_values:王五,45", "startTime": 2950080586.707023, "endTime": 2950080592.260519, "useTime": 5.556482791900635, "items": [{ "title": "请求发送完毕,等待反馈——成功!", "startTime": 2950080592.271186, "endTime": 2950080612.196954, "useTime": 19.944968223571777, "items": [] }, { "title": "获取数据库里添加完成的数据", "msg": "sql:SELECT * FROM node_user WHERE id = ?_values:王五,45", "startTime": 2950080615.264262, "endTime": 2950080616.479836, "useTime": 1.218986988067627, "items": [{ "title": "请求发送完毕,等待反馈——成功!", "startTime": 2950080616.488796, "endTime": 2950080624.55792, "useTime": 8.072536945343018, "items": [] }, { "title": "记录数据变化日志", "msg": "", "startTime": 2950080625.123253, "endTime": 0, "useTime": 0, "items": [] }] }] }] }] }
我们在写项目的时候,最郁闷的就是,运行的时候报错了,但是又不知道是哪一行出错了。如果某个函数被调用好几次,那么就更头疼了,到底是哪一次的调用出错了呢?
有了这个跟踪就能够很方便的知道到底是执行到了哪里出的错误,便于定位和修改。
ps:
这几天写代码的感受就是——糟糕透了。怪不得node都这么多年了还没火。真的太难驾驭了。