Node.Js+Knex+MySQL增删改查的简单示例(Typescript)

数据库:

CREATE DATABASE `MyDB`;
CREATE TABLE `t_users` (
  `user_id` int(11) NOT NULL,
  `user_name` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

项目结构:

package.json如下,拷贝并替换你们本地的package.json后运行 npm install 命令安装所需要的依赖。项目使用了nodemon+ts-node方便development

{
  "name": "tsdemo",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "@types/node": "^22.9.0",
    "nodemon": "^3.1.7",
    "ts-node": "^10.9.2",
    "typescript": "^5.6.3"
  },
  "dependencies": {
    "@types/express": "^5.0.0",
    "express": "^4.21.1",
    "knex": "^3.1.0",
    "mysql": "^2.18.1"
  }
}

nodemon.json:

{
    "watch": ["src/**/*.js", "src/**/*.ts", "util/**/*.ts"],  
    "ext": "js,ts,json",                       
    "ignore": ["node_modules", "dist"],       
    "exec": "ts-node src/index.ts",           
    "delay": "2500"                            
}
  

tsconfig.json:

{
  "compilerOptions": {
    "target": "es2016",     
    "module": "commonjs",                   
    "outDir": "./dist",                               
    "esModuleInterop": true,                             
    "forceConsistentCasingInFileNames": true,            
    "strict": true,             
    "skipLibCheck": true                                
  },
  "include": [
    "src/**/*"
, "util/**/*"  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

代码部分,VS Code推荐使用Fitten Code插件,目前免费的AI编程工具。可以检查错误,智能补全,代码解释等等,极大提高效率。

db.ts:

import { rejects } from "assert"
import { knex } from "knex"
import { resolve } from "path"

const db = knex({
  client: "mysql",
  connection: {
    host: "localhost",
    user: "root",
    password: "root",
    database: "MyDB"
  }
})

type UserRow = {
    user_id:number,
    user_name:string,
}
//增
export async function addUser(user_name:string) : Promise<string | null> {
  let user_id:number = 0
  await getMaxUserId().then((max_id) => {
    console.log("max_id: ", max_id)
    return new Promise((resolve, reject) => {
      if(max_id)
      {
        console.log("current max_id: ", max_id)
        user_id = max_id === null? 0 : max_id + 1
        console.log("new user_id: ", user_id)
        try{
          db("t_users").insert({user_id, user_name})
          console.log("add success")
          resolve("add success")
        }catch(error){
          console.error(error)
          reject("add failed")
        }
      }
    })
  })
  return null
}
//删
export async function deleteUser(user_id:number) : Promise<string | null> {
  const user = await getUserById(user_id);
    
  return new Promise((resolve, reject) => {
      if (user) {
          try {
              db("t_users").where("user_id", user_id).del().then(() => { 
                  console.error("delete success");
                  resolve("delete success");
              }).catch(error => {
                  console.error("delete failed", error);
                  reject("delete failed");
              });
          } catch (error) {
              console.error(error);
              reject("delete failed");
          }
      } else {
          console.error("user not found");
          resolve("user not found"); 
      }
  });
}
//改
export async function updateUser(user_id:number, user_name:string) : Promise<string | null> {
  const user = await getUserById(user_id);
  return new Promise((resolve, reject) => {
      if (user) {
          try {
              db("t_users").where("user_id", user_id).update({user_name}).then(() => { 
                  console.error("update success");
                  resolve("update success");
              }).catch(error => {
                  console.error("update failed", error);
                  reject("update failed");
              });
          } catch (error) {
              console.error(error);
              reject("update failed");
          }
      } else {
          console.error("user not found");
          resolve("user not found"); 
      }
  });
} 
//查
export async function getUsers() : Promise<UserRow[] | null> {
    try {
      const users = await db("t_users").select("*")
      console.log(users)
      return users
    } catch (error) {
      console.error(error)
      return null
    }
}

export async function getMaxUserId() : Promise<number | null> {  
  try {
    const max_id = await db("t_users").max("user_id as max");
    if(max_id && max_id.length > 0) {
      return max_id[0].max;
    } else {
      return null;  
    }
  } catch (error) {
    console.error(error);
    return null;  
  }
}

export async function getUserById(user_id:number) : Promise<UserRow | null> {  
    try{
      const user = await db("t_users").select("*").where("user_id", user_id).first()
      console.log(user)
      return user
    }catch(error){  
        console.error(error)
        return null
    }
}

export default db

index.ts:

import  * as userdb  from '../util/db';
import express, {Express, Request, Response} from 'express'
import bodyParser from 'body-parser';

const app : Express = express();
app.use(bodyParser.json());
//增
app.post('/adduser', (req : Request, res : Response) => {
    const user_name = req.body.user_name;
    userdb.addUser(user_name).then((resolve) => {        
        res.send(resolve);
     }).catch((error) => { res.send(error) });
});
//查
app.get('/getusers', (req : Request, res : Response) => {
    userdb.getUsers().then((user) => { 
        if(user != null)
        {
            res.send(JSON.stringify(user));
        }
        else
        {
            res.send('no user found');
        }
     }).catch((error) => { res.send(error) });  
});
//删
app.post('/deleteuser', (req : Request, res : Response) => {
    const user_id = req.body.user_id;
    userdb.deleteUser(user_id).then((resolve) => {     
        res.send(resolve);
     }).catch((error) => { res.send(error) });
});
//改
app.post('/updateuser', (req : Request, res : Response) => {
    const user_id = req.body.user_id;
    const user_name = req.body.user_name;
    userdb.updateUser(user_id, user_name).then((resolve) => {     
        res.send(resolve);
     }).catch((error) => { res.send(error) });
});



app.listen(3000, () => {
    const currentDate = new Date(); 
    const formattedDate = currentDate.toLocaleString();
    console.log(`server started on port 3000 at ${formattedDate}`);
});

npm start 运行

因为使用了ts-node,所以如果需要生成的js文件,运行tsc命令即可

推荐使用VS Code的插件REST Client进行测试。

测试文件 .http 示例如下:

###
GET http://localhost:3000/getusers

###
POST http://localhost:3000/adduser
Content-Type: application/json

{
    "user_name": "admin"
}

###
POST http://localhost:3000/deleteuser
Content-Type: application/json

{
    "user_id": 1
}

###
POST http://localhost:3000/updateuser
Content-Type: application/json

{
    "user_id": 1,
    "user_name": "admin111"
}

部分测试结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/916612.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

fastadmin多个表crud连表操作步骤

1、crud命令 php think crud -t xq_user_credential -u 1 -c credential -i voucher_type,nickname,user_id,voucher_url,status,time --forcetrue2、修改控制器controller文件 <?phpnamespace app\admin\controller;use app\common\controller\Backend;/*** 凭证信息…

【论文阅读】利用SEM二维图像表征黏土矿物三维结构

导言 在油气储层研究中&#xff0c;黏土矿物对流体流动的影响需要在微观尺度上理解&#xff0c;但传统的二维SEM图像难以完整地表征三维孔隙结构。常规的三维成像技术如FIB-SEM&#xff08;聚焦离子束扫描电子显微镜&#xff09;虽然可以获取高精度的3D图像&#xff0c;但成本…

JavaScript 中的 undefined 、null 与 NaN :概念解析与对比

文章目录 &#x1f4af;前言&#x1f4af;undefined1. 什么是 undefined2. undefined 的使用场景3. undefined 的特性 &#x1f4af;null1. 什么是 null2. null 的使用场景3. null 的特性 &#x1f4af;NaN1. 什么是 NaN2. NaN 的使用场景3. NaN 的特性 &#x1f4af;三者的区别…

C++编程技巧与规范-类和对象

类和对象 1. 静态对象的探讨与全局对象的构造顺序 静态对象的探讨 类中的静态成员变量(类类型静态成员) 类中静态变量的声明与定义&#xff08;类中声明类外定义&#xff09; #include<iostream> using namespace std;namespace _nmspl {class A{public:A():m_i(5){…

python遇到问题

1&#xff0c;BeautifulSoup lxml 解析器安装 问 1&#xff0c;BeautifulSoup lxml 解析器安装2&#xff0c;BeautifulSoup 如何引入第三方库 BeautifulSoup lxml&#xff0c;默认是导入的是python内置的解析器答1 1. 安装 Python 和 pip 确保你已经安装了 Python 和 pip。你…

async 和 await的使用

一、需求 点击按钮处理重复提交&#xff0c;想要通过disabled的方式实现。 但是点击按钮调用的方法里有ajax、跳转、弹窗等一系列逻辑操作&#xff0c;需要等方法里流程都走完&#xff0c;再把disabled设为false&#xff0c;这样下次点击按钮时就可以继续走方法里的ajax等操作…

MacOS下,如何在Safari浏览器中打开或关闭页面中的图片文字翻译功能

MacOS下&#xff0c;如何在Safari浏览器中打开或关闭页面中的图片文字翻译功能 在Mac上的Safari浏览器中&#xff0c;可以通过实况文本功能来实现图片中的文本翻译。关闭步骤具体步骤如下&#xff1a; 在浏览器地址栏&#xff0c;鼠标右击翻译按钮&#xff0c;然后点击“首选…

31.2 DOD压缩和相关的prometheus源码解读

本节重点介绍 : 时序数据时间的特点DOD压缩原理讲解dod压缩过程讲解dod压缩 prometheus源码解读 时序数据时间的特点 持续采集采集间隔固定&#xff0c;如prometheus配置job中的scrape_interval参数每隔15秒采集一次 - job_name: node_exporterhonor_timestamps: truescrape…

推荐一款好用的ios传输设备管理工具:AnyTrans for iOS

AnyTrans for iOS是一款好用的ios传输设备管理工具&#xff0c;可以方便用户对iphone、ipad、ipod中的文件进行管理操作&#xff0c;可以方便用户在电脑上进行各类文件的管理操作&#xff0c;支持联系人、视频、音频、短信、图片等文件的导入&#xff0c;软件支持双向传输和浏览…

快速利用c语言实现线性表(lineList)

线性表是数据结构中最基本和简单的一个&#xff0c;它是n的相同类型数据的有序序列&#xff0c;我们也可以用c语言中的数组来理解线性表。 一、线性表声明 我们定义一个线性表的结构体&#xff0c;内部有三个元素&#xff1a;其中elem是一个指针&#xff0c;指向线性表的头&am…

计算机毕业设计Python+CNN卷积神经网络股票预测系统 股票推荐系统 股票可视化 股票数据分析 量化交易系统 股票爬虫 股票K线图 大数据毕业设计 AI

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

QT QLineEdit失去焦点事件问题与解决

本文介绍如何获得QLineEdit的失去焦点事件和获得焦点的输入框也会触发失去焦点事件的问题&#xff01; 目录 一、QLineEdit获得失去焦点事件 1.自定义类继承自QLineEdit 2.重写 focusOutEvent 3.使用 二、失去焦点事件问题 1.问题描述 2.问题解决 三、源码分享 lineed…

vscode执行npm install报错

npm install一直提示报错 以管理员身份运行vscode&#xff0c;如果每次觉得很麻烦可以做如下修改&#xff1a;

【算法】树状数组

前言 众所周知&#xff0c;通过前缀和&#xff0c;我们可以很快的在一个很大的数组中求出区间和&#xff0c;但是如果想要去修改数组中的一个数的值&#xff0c;前缀和就无法实现。所以来学习一个新的数据结构&#xff1a;树状数组 &#xff08;文章中关于树状数组的截图来自于…

Java项目实战II基于微信小程序的私家车位共享系统(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在城市化进…

ZeroSSL HTTPS SSL证书ACMESSL申请3个月证书

目录 一、引言 二、准备工作 三、申请 SSL 证书 四、证书选型 五、ssl重要性 一、引言 目前免费 Lets Encrypt、ZeroSSL、BuyPass、Google Public CA SSL 证书&#xff0c;一般免费3-6个月。从申请难易程度分析&#xff0c;zerossl申请相对快速和简单&#xff0c;亲测速度非…

pipx安装提示找不到包

执行&#xff1a; pipx install --include-deps --force "ansible6.*"WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection broken by NewConnectionError(<pip._vendor.urllib3.connection.HTTPSConnection …

react + ts定义接口类型写法

接口&#xff08;未进行ts定义&#xff09; export async function UserList(params: {// keyword?: string;current?: number;pageSize?: number;},// options?: { [key: string]: any }, ) {return request<API1.UserList>(http://geek.itheima.net/v1_0/mp/artic…

Golang超详细入门教程

Golang超详细入门教程 部分图片可能加载不出来&#xff0c;所以这里我上传到了自己的个人网站上也可以查看&#xff1a;http://dahua.bloggo.chat/testimonials/490.html 一、数据类型转换 C语言中数据可以隐式转换或显示转换, 但是Go语言中数据只能显示转换格式: 数据类型(…

Cannot resolve org.apache.tomcat.embed:tomcat-embed-core:9.0.60标红解决办法

解决方法是&#xff1a; MyBatis 会扫描这个包下的所有接口&#xff0c;并将这些接口注册为 MyBatis 的 Mapper。 把这个加上后&#xff0c;问题解决&#xff01;