node.js + mysql 实现数据添加的功能。万事基于服务!

增删改查之添加数据。

优点:只需要设置一个json文件,就可以实现基本的添加功能,可以视为是零代码。

添加数据的服务实现的功能:

1、  添加一条记录、多条记录(批量添加)、主从表记录

2、  记录访问日志

3、  记录数据变化记录

4、  执行步骤跟踪和计时

5、  异常日志

6、  权限判断

步骤:

1、  数据库设计、建表这类的直接略过,假设有了一张表,我们要往这个表里面添加数据

2、  根据要添加的字段,设置一个json文件,对服务进行描述,并且给这个服务设置一个变化,作为区分。

3、  客户端提交数据和服务变化。

4、  服务器端,获取数据和服务变化,调用对应的程序进行处理。

5、  处理完毕后处理返回给客户的信息

6、  如果有特殊业务需求,可以用插件的方式来实现。

7、  完成

第一步,不管用什么方式做项目,都是要做的。

第二步需要弄一个json文件,这个可以自动生成,不用手写

第三步相当于做一个路由,路由规则制定好了就不用再写代码了。

第四步由框架完成,不需要写代码

第五步判断一下是否成功,按照规则给浏览器返回数据,也不用一遍一遍写。

第六步不是必须的,大部分的增删改查都是不需要插件的。

所以,基本上做一个json文件,就可以搞定一个服务。需要写的代码无限接近零代码。而json文件又可以自动生成。

下面是json文件的例子:(这个可以自动生成)

  1. {
  2. "operationMode":"add",
  3. "pluginBefore":"",
  4. "pluginAfter":"",
  5. "tableInfo":{
  6. "tableName": "node_user",
  7. "primaryKey":"id",
  8. "sql": "INSERT INTO node_user(id,name,age) VALUES(0,?,?)" ,
  9. "sqlSelect": "SELECT * FROM node_user WHERE id = ?" ,
  10. "column":["name","age"]
  11.  
  12. }
  13.  
  14. }

然后再说一下代码类型,可以分为两类——框架类和项目类

像.net框架、ado.net、express这类,内部的实现代码都是属于框架级的,内部有再多的代码,也不应该算到项目里面。

而调用类库、使用框架实现项目的代码,才是项目级的代码,才算作代码量。

这个要先说清楚,然后再发后面的代码。

http的使用,属于项目级的,http的内部实现,就是框架级的。

同理,添加服务的调用部分属于项目级的,服务内部的实现代码属于框架级的。

先不上http了,写一个简单的测试用代码,优点是不用打开浏览器就可以进行测试。要不然每次都要打开浏览器,太麻烦了。

这个不是正式的代码,仅仅是初期测试用的。这个是项目级别的代码。

  1. /**
  2. * Created by jyk00 on 2019/3/31.
  3. * curd的服务
  4. */
  5.  
  6. //测试添加服务
  7.  
  8. //精确计时
  9. var time = require('../preciseTime').time;
  10. //创建添加服务对象
  11. var service = require('./serviceAdd');
  12.  
  13. var trace={
  14. title:'收到一个请求:100',
  15. msg:'',
  16. startTime:time(),
  17. endTime:0,
  18. useTime:0,
  19. items:[]
  20. };
  21.  
  22. service.start(100,trace,function (err,info) {
  23.  
  24. msg.endTime = time();
  25. msg.useTime = time() - msg.startTime;
  26.  
  27. console.log('完成服务:'+JSON.stringify(trace));
  28.  
  29. });

添加服务的代码(业务层) 框架级代码

  1. /**
  2. * Created by jyk00 on 2019/3/31.
  3. * 添加数据的服务
  4. */
  5.  
  6. exports.start = function(code,trace,callback) {
  7. //精确计时
  8. var time = require('../preciseTime').time;
  9.  
  10. var traceAdd = {
  11. title:'开始添加数据的服务',
  12. msg:'',
  13. startTime:time(),
  14. endTime:0,
  15. useTime:0,
  16. items:[]
  17. };
  18.  
  19. trace.items.push(traceAdd);
  20.  
  21. /** 根据配置信息实现添加数据的功能
  22. * 获取服务信息
  23. * 接收数据
  24. * 验证数据
  25. * 调用插件
  26. * 持久化
  27. * 获取持久化后数据
  28. * 写数据变化日志
  29. * 返回结果
  30. */
  31.  
  32. //获取服务信息
  33. //console.log('服务ID:' + code);
  34. var meta = require('./service_'+ code +'.json');
  35. console.log('获取服务信息:' + meta);
  36.  
  37. //获取实体类,先模拟一下
  38. var data = require('./node_user.json');
  39.  
  40. var info={
  41. trace:traceAdd,
  42. requestId:0,
  43. serviceId:code,
  44. data:data,
  45. table:meta.tableInfo
  46. };
  47.  
  48. //验证数据,暂时略
  49.  
  50. //调用持久化前的插件
  51. var plugName = meta.pluginBefore;
  52. if (plugName.length === 0){
  53. //没有插件,不调用
  54. console.log('没有插件,不调用');
  55. //持久化及后续
  56. saveAndLast(data);
  57. }
  58. else
  59. {
  60. //有插件
  61. console.log('有插件,调用');
  62. var plug = require('../plugin/' + plugName);
  63. plug.begin(data,function(data){
  64. //持久化及后续
  65. saveAndLast(data);
  66. });
  67.  
  68. }
  69.  
  70. //持久化以及之后的事情
  71. function saveAndLast(data) {
  72. //持久化之添加数据
  73. var db = require('./dataBaseAdd');
  74.  
  75. //持久化
  76. db.query(info,function(err, result){
  77. console.log('saveData的回调:' );
  78. console.log('result:',result);
  79.  
  80. //调用持久化之后的插件
  81. plugName = meta.pluginAfter;
  82. if (plugName.length === 0){
  83. //没有插件,不调用
  84.  
  85. }
  86. else{
  87. //有插件
  88. plug = require('../plugin/' + plugName);
  89. plug.begin(err, result,data,function() {
  90.  
  91. });
  92. }
  93.  
  94. });
  95.  
  96. }
  97.  
  98. };

持久化的代码(数据层) 框架级代码

  1. /**
  2. * Created by jyk00 on 2019/4/1.
  3. * 数据服务之添加操作
  4.  
  5. */
  6. //持久化内部的跟踪
  7. var traceStartAddData = {};
  8. //捕捉异常
  9. process.on('uncaughtException', function (err) {
  10. console.log('uncaughtException的trace:' +JSON.stringify(traceStartAddData));
  11. console.log("捕捉到异常啦");
  12. console.log(err);
  13.  
  14. });
  15.  
  16. exports.query = function(info,callback) {
  17. //精确计时
  18. var time = require('../preciseTime').time;
  19.  
  20. //持久化之添加数据
  21. traceStartAddData = {
  22. title:'持久化之添加数据',
  23. msg:'',
  24. startTime:time(),
  25. endTime:0,
  26. useTime:0,
  27. items:[]
  28. };
  29.  
  30. info.trace.items.push(traceStartAddData);
  31.  
  32. /** 根据配置信息实现添加数据的功能
  33. * 获取表信息
  34. * 接收传入的数据,验证任务由上层搞定
  35. * 持久化
  36. * 获取持久化后数据
  37. * 写数据变化日志
  38. * 返回结果
  39. */
  40.  
  41. //==================获取表信息和数据=================================
  42. var traceGetInfo = {
  43. title:'获取表信息和数据、定义dataChange',
  44. msg:'',
  45. startTime:time(),
  46. endTime:0,
  47. useTime:0,
  48. items:[]
  49. };
  50.  
  51. traceStartAddData.items.push(traceGetInfo);
  52.  
  53. //获取表信息
  54. var tableInfo = info.table;
  55. //获取实体类
  56. var data = info.data;
  57.  
  58. //记录数据变化情况
  59. var dataChange = {
  60. requestId:info.requestId,
  61. serviceId:info.serviceId,
  62. tableID:info.table.tableId,
  63. dataID:0,
  64. oldDataJson:'',
  65. newDataJson:'',
  66. submitDataJson:JSON.stringify(info.data),
  67. dbResult:'',
  68. trace:JSON.stringify(info.trace),
  69. addUserid:1
  70. };
  71. traceGetInfo.endTime = time();
  72. traceGetInfo.useTime = time() - traceGetInfo.startTime;
  73.  
  74. //==================创建MySql对象=================================
  75. var traceCreateMySql = {
  76. title:'创建MySql对象、cnString、connection',
  77. msg:'',
  78. startTime:time(),
  79. endTime:0,
  80. useTime:0,
  81. items:[]
  82. };
  83. traceStartAddData.items.push(traceCreateMySql);
  84.  
  85. //创建mysql对象
  86. var mysql = require('mysql');
  87. var cnString = require('../sqlConnection.json');
  88. var connection = mysql.createConnection(cnString);
  89.  
  90. traceCreateMySql.endTime = time();
  91. traceCreateMySql.useTime = time() - traceCreateMySql.startTime;
  92.  
  93. //==================发送持久化请求=================================
  94. var traceAddNewData = {
  95. title:'准备发送持久化请求,添加一条数据',
  96. msg:'',
  97. startTime:time(),
  98. endTime:0,
  99. useTime:0,
  100. items:[]
  101. };
  102.  
  103. traceStartAddData.items.push(traceAddNewData);
  104.  
  105. var sql = tableInfo.sql;
  106. //数据转换成数组
  107. var valuesParams = createParams(tableInfo,data);
  108.  
  109. myQuery(sql,valuesParams,traceAddNewData,function (err, result) {
  110. //数据添加完成后的回调
  111. //console.log('持久化的回调的trace:' +JSON.stringify(traceStartAddData));
  112.  
  113. if(err){
  114. console.log('[INSERT ERROR ] - ',err.message);
  115. traceAddNewData.msg += '_err:' + JSON.stringify(err);
  116. callback(err, result);
  117. return;
  118. }
  119.  
  120. //记录数据变化记录,
  121. var log = require('./serviceAdd_11.json');
  122. //记录添加数据后的返回信息
  123. dataChange.dbResult = JSON.stringify(result);
  124.  
  125. //从数据库里获取刚添加的数据
  126. var traceGetNewData = {
  127. title:'获取数据库里添加完成的数据',
  128. msg:'',
  129. startTime:time(),
  130. endTime:0,
  131. useTime:0,
  132. items:[]
  133. };
  134. traceAddNewData.items.push(traceGetNewData);
  135.  
  136. myQuery(tableInfo.sqlSelect,[result.insertId],traceGetNewData,function (err, result) {
  137. //获取一条记录完毕
  138. //console.log('获取更新数据的回调result:' +JSON.stringify(result));
  139. //console.log('获取更新数据的回调的trace:' +JSON.stringify(traceStartAddData));
  140.  
  141. //记录数据变化日志
  142. var traceAddlog = {
  143. title:'记录数据变化日志',
  144. msg:'',
  145. startTime:time(),
  146. endTime:0,
  147. useTime:0,
  148. items:[]
  149. };
  150. traceGetNewData.items.push(traceAddlog);
  151.  
  152. //数据库里的新数据
  153. dataChange.newDataJson = JSON.stringify(result);
  154. //目前为止的跟踪记录
  155. dataChange.trace = JSON.stringify(info.trace);
  156. valuesParams = createParams(log.tableInfo,dataChange);
  157.  
  158. //提交操作
  159. myQuery(log.tableInfo.sql,valuesParams,traceAddlog,function (err, result){
  160. //数据变化日志回调完毕
  161. console.log('数据变化日志回调完毕:' +JSON.stringify(info.trace));
  162.  
  163. });
  164.  
  165. });
  166. connection.end();
  167.  
  168. //回调,不等数据变化的日志了
  169. callback(err, result);
  170.  
  171. });
  172.  
  173. //console.log('调用结束等待结果');
  174.  
  175. //封装数据库操作,以及计时器
  176. function myQuery(sql,vParme,traces,callback) {
  177. //console.log('myQuery的sql:' +sql);
  178. traces.msg += 'sql:'+sql;
  179. traces.msg += '_values:' + valuesParams;
  180.  
  181. var conn = mysql.createConnection(cnString);
  182. conn.connect();
  183. conn.query(sql,vParme,function (err, result) {
  184. //console.log('myQuery的回调:' +err);
  185.  
  186. traceStart.endTime = time();
  187. traceStart.useTime = time() - traceStart.startTime;
  188.  
  189. if(err){
  190. console.log('[ERROR ] - ',err.message);
  191. traceStart.title += '——执行出错:'+ err.message;
  192. traceStart.error = JSON.stringify(err)
  193. callback(err, result);
  194. return;
  195. }
  196. traceStart.title += '——成功!';
  197.  
  198. callback(err, result);
  199.  
  200. });
  201. conn.end();
  202. //请求发送完毕
  203. //console.log('请求发送完毕:');
  204.  
  205. traces.endTime = time();
  206. traces.useTime = time() - traces.startTime;
  207.  
  208. //记录完成开始时间
  209. var traceStart = {
  210. title:'请求发送完毕,等待反馈',
  211. startTime:time(),
  212. endTime:0,
  213. useTime:0,
  214. items:[]
  215. };
  216.  
  217. traces.items.push(traceStart);
  218. }
  219.  
  220. //拼接valuesParams
  221. function createParams(colInfo,data){
  222. //console.log('开始拼接数据数组');
  223. var valuesParams = [];
  224. //数据变成数组的形式
  225. var colName = "";
  226. for (var i=0 ;i<colInfo.column.length;i++) {
  227. colName = colInfo.column[i];
  228. valuesParams.push(data[colName]);
  229. }
  230.  
  231. return valuesParams;
  232.  
  233. }
  234.  
  235. //拼接sql
  236. function createSql2(){
  237.  
  238. sql = 'INSERT INTO ' +meta.tableName ;
  239.  
  240. var cols = "(" + meta.primaryKey;
  241. var values = " VALUES(0";
  242. var valuesParams = [];
  243.  
  244. //拼接字段名和参数
  245. for (var key in meta.cols) {
  246. cols += ',' + key;
  247. values += ',?';
  248. valuesParams.push(meta.cols[key]);
  249. }
  250. sql +=cols + ')' + values + ')';
  251. console.log(sql);
  252.  
  253. }
  254.  
  255. };

跟踪记录

  1. {
  2. "title": "开始添加数据的服务",
  3. "msg": "",
  4. "startTime": 2950080457.323715,
  5. "endTime": 0,
  6. "useTime": 0,
  7. "items": [{
  8. "title": "持久化之添加数据",
  9. "msg": "",
  10. "startTime": 2950080463.596571,
  11. "endTime": 0,
  12. "useTime": 0,
  13. "items": [{
  14. "title": "获取表信息和数据、定义dataChange",
  15. "msg": "",
  16. "startTime": 2950080463.608944,
  17. "endTime": 2950080463.683611,
  18. "useTime": 0.08490705490112305,
  19. "items": []
  20. }, {
  21. "title": "创建MySql对象、cnString、connection",
  22. "msg": "",
  23. "startTime": 2950080463.702811,
  24. "endTime": 2950080586.696783,
  25. "useTime": 122.99781227111816,
  26. "items": []
  27. }, {
  28. "title": "准备发送持久化请求,添加一条数据",
  29. "msg": "sql:INSERT INTO node_user(id,name,age) VALUES(0,?,?)_values:王五,45",
  30. "startTime": 2950080586.707023,
  31. "endTime": 2950080592.260519,
  32. "useTime": 5.556482791900635,
  33. "items": [{
  34. "title": "请求发送完毕,等待反馈——成功!",
  35. "startTime": 2950080592.271186,
  36. "endTime": 2950080612.196954,
  37. "useTime": 19.944968223571777,
  38. "items": []
  39. }, {
  40. "title": "获取数据库里添加完成的数据",
  41. "msg": "sql:SELECT * FROM node_user WHERE id = ?_values:王五,45",
  42. "startTime": 2950080615.264262,
  43. "endTime": 2950080616.479836,
  44. "useTime": 1.218986988067627,
  45. "items": [{
  46. "title": "请求发送完毕,等待反馈——成功!",
  47. "startTime": 2950080616.488796,
  48. "endTime": 2950080624.55792,
  49. "useTime": 8.072536945343018,
  50. "items": []
  51. }, {
  52. "title": "记录数据变化日志",
  53. "msg": "",
  54. "startTime": 2950080625.123253,
  55. "endTime": 0,
  56. "useTime": 0,
  57. "items": []
  58. }]
  59. }]
  60. }]
  61. }]
  62. }

我们在写项目的时候,最郁闷的就是,运行的时候报错了,但是又不知道是哪一行出错了。如果某个函数被调用好几次,那么就更头疼了,到底是哪一次的调用出错了呢?

有了这个跟踪就能够很方便的知道到底是执行到了哪里出的错误,便于定位和修改。

ps:

这几天写代码的感受就是——糟糕透了。怪不得node都这么多年了还没火。真的太难驾驭了。

零代码第一步,做个添加数据的服务先。node.js + mysql的更多相关文章

  1. Node.js + MySQL 实现数据的增删改查

    通过完成一个 todo 应用展示 Node.js + MySQL 增删改查的功能.这里后台使用 Koa 及其相应的一些中间件作为 server 提供服务. 初始化项目 $ mkdir node-cru ...

  2. Qt 学习第一步 做计划和确定目标

    接下来開始一步步深入学习Qt. 学习的第一步是整理资料,也就是找书和sample. 逛了一些论坛,推荐以下3本书 1> C++ GUI programming with Qt 4(2nd Edi ...

  3. RabbitMQ代码第一步

    Hello RabbitMQ 终于到了使用.Net连接RabbitMQ的时候了,我们首先新建一个控制台应用程序,在程序包管理控制器中NuGet中下载 RabbitMQ. Install-Package ...

  4. Scrapyd 改进第一步: Web Interface 添加 charset=UTF-8, 避免查看 log 出现中文乱码

    0.问题现象和原因 如下图所示,由于 Scrapyd 的 Web Interface 的 log 链接直接指向 log 文件,Response Headers 的 Content-Type 又没有声明 ...

  5. 菜鸟笔记:node.js+mysql中将JSON数据构建为树(递归制作树状菜单数据接口)

    初学Web端开发,今天是第一次将所学做随笔记录,肯定存在多处欠妥,望大家海涵:若有不足,望大家批评指正. 进实验室后分配到的第一个项目,需要制作一个不确定层级树形菜单的数据接口,对于从来没实战编过程的 ...

  6. Node.js的学习--使用cheerio抓取网页数据

    打算要写一个公开课网站,缺少数据,就决定去网易公开课去抓取一些数据. 前一阵子看过一段时间的Node.js,而且Node.js也比较适合做这个事情,就打算用Node.js去抓取数据. 关键是抓取到网页 ...

  7. 使用Node.js实现数据推送

    业务场景:后端更新数据推送到客户端(Java部分使用Tomcat服务器). 后端推送数据的解决方案有很多,比如轮询.Comet.WebSocket. 1. 轮询对于后端来说开发成本最低,就是按照传统的 ...

  8. 好未来数据中台 Node.js BFF实践(一):基础篇

    好未来数据中台 Node.js BFF实践系列文章列表: 基础篇 实战篇(TODO) 进阶篇(TODO) 好未来数据中台的Node.js中间层从7月份开始讨论可行性,截止到9月已经支持了4个平台,其中 ...

  9. JS一般般的网页重构可以使用Node.js做些什么(转)

    一.非计算机背景前端如何快速了解Node.js? 做前端的应该都听过Node.js,偏开发背景的童鞋应该都玩过. 对于一些没有计算机背景的,工作内容以静态页面呈现为主的前端,可能并未把玩过Node.j ...

随机推荐

  1. 多媒体管理器解析IMultimediaManager

    一.基本API bool Available { get; } bool Working { get; } AdvancedOptions Advanced { get; } 二.作为通信引擎 str ...

  2. 微信小程序客服消息开发实战:实时在手机上接收小程序客服消息通知,以及在手机上回复

    在微信小程序开发中,可以非常方便的集成客服功能,只需要一行代码便可以将用户引导至客服会话界面.这行代码就是: <button open-type="contact" bind ...

  3. Java引用详解-StrongReference SoftReference WeakReference PhantomReference

    1 Java引用介绍 Java从1.2版本开始引入了4种引用,这4种引用的级别由高到低依次为:    强引用  >  软引用  >  弱引用  >  虚引用 ⑴强引用(StrongR ...

  4. C# 4.0 的 Visual Studio 2010 示例

    C# 4.0 的 Visual Studio 2010 示例 我们将 C# 示例分为两种不同的类别: 语言示例 LINQ 示例 语言示例 语言示例帮助您熟悉各种 C# 语言功能.这些示例包含在 Lan ...

  5. #Java学习之路——基础阶段二(第七篇)

    我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...

  6. Mac电脑上一款非常时尚高清的动态壁纸Living Wallpaper HD

    很多朋友Mac电脑上都喜欢用动态壁纸,Living Wallpaper HD是本人尝试的一款非常不错的高清动态壁纸.有时钟.天气等各种组建,非常时尚美观. Living Wallpaper HD下载地 ...

  7. Python爬虫入门教程 50-100 Python3爬虫爬取VIP视频-Python爬虫6操作

    爬虫背景 原计划继续写一下关于手机APP的爬虫,结果发现夜神模拟器总是卡死,比较懒,不想找原因了,哈哈,所以接着写后面的博客了,从50篇开始要写几篇python爬虫的骚操作,也就是用Python3通过 ...

  8. django插入数据库错误:mysql的1267错误

    错误信息: django.db.utils.OperationalError: (1267, "Illegal mix of collations (latin1_swedish_ci,IM ...

  9. LindDotNetCore~授权中间件的介绍

    回到目录 LindDotNetCore中间件 大叔认识中间件就是主要对http请求进行拦截,然后添加具体个性化功能的逻辑,这种把请求切开,添加新逻辑的方式一般称为面向方面的逻辑AOP! 授权中间件 请 ...

  10. 104 - kube-scheduler源码分析 - predicate整体流程

    (注:从微信公众:CloudGeek复制过来,格式略微错乱,更好阅读体验请移步公众号,二维码在文末) 今天我们来跟一下predicates的整个过程:predicate这个词应该是“断言.断定”的意思 ...