Nodejs express+knex(ORM框架)

knex

上一个文章中我们还使用sql语句去编写接口,在实际工作中我们很少用到sql语句,sql语句编写起来比较繁琐,还有sql注入风险。

Knex是一个基于JavaScript的查询生成器,它允许你使用JavaScript代码来生成和执行SQL查询语句。它提供了一种简单和直观的方式来与关系型数据库进行交互,而无需直接编写SQL语句。你可以使用Knex定义表结构、执行查询、插入、更新和删除数据等操作。

knexjs.org/guide/query...

Knex的安装和设置

knex支持多种数据库 pg sqlite3 mysql2 oracledb tedious

用什么数据库安装对应的数据库就行了

sh 复制代码
#安装knex
$ npm install knex --save

#安装你用的数据库
$ npm install pg
$ npm install pg-native
$ npm install sqlite3
$ npm install better-sqlite3
$ npm install mysql
$ npm install mysql2
$ npm install oracledb
$ npm install tedious

连接数据库

js 复制代码
import knex from 'knex'
const db = knex({
    client: "mysql2",
    connection: config.db
})
yaml 复制代码
db:
  user: root
  password: '123456'
  host: localhost
  port: 3306
  database: xiaoman

实现增删改差和连表

js 复制代码
// import mysql2 from "mysql2/promise";
import * as jsyaml from "js-yaml";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import express from "express";
import knex from "knex";

// ESM 获取当前文件所在目录路径
const __filename = fileURLToPath(import.meta.url); //C:\CN\全栈AI\node\nodecode\mysql-express-yaml\index.js
const __dirname = path.dirname(__filename); //C:\CN\全栈AI\node\nodecode\mysql-express-yaml
console.log(__filename, __dirname);
// 读取 db.config.yaml 文件
const yamlText = fs.readFileSync(
  path.join(__dirname, "./db.config.yaml"),
  "utf8"
);
const config = jsyaml.load(yamlText);

// 创建数据库连接------是异步的,所以下面都要用async await
// const sql = await mysql2.createConnection({
//   ...config.db,
// });
// console.log('sql', sql)

const db = knex({
  client: "mysql2",
  connection: config.db,
});
// knex所有代码直接编写是没有效果的,需要.then才会起效果
db.schema
  .createTableIfNotExists("list", (table) => {
    table.increments("id"); //id自增
    table.integer("age"); //age 整数
    table.string("name"); //name 字符串
    table.string("hobby"); //hobby 字符串
    table.timestamps(true, true); //创建时间和更新时间
  })
  .then(() => {
    console.log("创建成功");
  });

const app = express();
app.use(express.json());

//查询接口 全部
app.get("/", async (req, res) => {
  // const [data] = await sql.query("select * from user");
  const data = await db("user").select().orderBy("id", "desc");
  const count = await db("user").count("* as total");
  // [{total: 1}]
  // db.raw("select * from user").then((data) => {
  //   console.log(data); //也是可以从数据库中查询到
  // });

  // 连表------高级玩法
  const table = await db("user")
    .select()
    .leftJoin("table", "user.id", "table.user_id");
  res.json({
    data,
    table,
    total: count[0].total,
    // sql: db("list").select().toSQL().sql 可以用来调试
  });
});
//单个查询 params
app.get("/user/:id", async (req, res) => {
  const row = await db("list").select().where({ id: req.params.id });
  // const [row] = await sql.query(
  //   `select * from user where id = ${req.params.id}`
  // );
  // const [row] = await sql.query(`select * from user where id = ?`, [
  //   req.params.id,
  // ]);
  res.send(row);
});

//新增接口
app.post("/create", async (req, res) => {
  const { name, age, hobby } = req.body;
  await db("list").insert({ name, age, hobby });
  // await sql.query(`insert into user(name,age,address) values(?,?,?)`, [
  //   name,
  //   age,
  //   address,
  // ]);
  res.send({ ok: 1 });
});

//编辑
app.post("/update", async (req, res) => {
  const { name, age, hobby, id } = req.body;
  await db("list").update({ name, age, hobby }).where({ id });
  // await sql.query(`update user set name = ?,age = ?,address = ? where id = ?`, [
  //   name,
  //   age,
  //   address,
  //   id,
  // ]);
  res.send({ ok: 1 });
});
//删除
app.post("/delete", async (req, res) => {
  // await sql.query(`delete from user where id = ?`, [req.body.id]);
  await db("list").delete().where({ id: req.body.id });
  res.send({ ok: 1 });
});
const port = 3000;

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

事务

你可以使用事务来确保一组数据库操作的原子性,即要么全部成功提交,要么全部回滚

例如A给B转钱,需要两条语句,如果A语句成功了,B语句因为一些场景失败了,那这钱就丢了,所以事务就是为了解决这个问题,要么都成功,要么都回滚,保证金钱不会丢失。

js 复制代码
//伪代码
db.transaction(async (trx) => {
    try {
        await trx('list').update({money: -100}).where({ id: 1 }) //A
        await trx('list').update({money: +100}).where({ id: 2 }) //B
        await trx.commit() //提交事务
    }
    catch (err) {
        await trx.rollback() //回滚事务
    } 
}).then(() => {
   console.log('成功')
}).catch(() => {
   console.log('失败')
})
相关推荐
薛定谔的猫-菜鸟程序员11 分钟前
Electron开发超详细教程(从入门到放弃)
前端·javascript·electron
最强小杰32 分钟前
DeepSeek V4 Flash + Codex CLI 接入教程:原生 Responses API 适配,从配置到跑通收藏这篇就够了(2026)
java·前端·python·ai
静水leo1 小时前
使用 Whistle 拦截接口并模拟后端响应
前端
掘金者阿豪1 小时前
SQL Server数据迁移完成后,凌晨的数据库告警该怎么查?
前端·后端
JudithHuang1 小时前
React 嵌套路由与布局
前端·react.js·arcgis·react·react router
htzyl2061 小时前
前端阶梯——第四十三章、实战二:待办清单To-Do
前端·javascript·html
摹客2 小时前
【3D设计】界面设计中的3D元素:应用场景+5款工具横评(含Three.js)
前端
Hilaku2 小时前
CORS 到底在保护谁?90% 的前端理解错了跨域的本质
前端·javascript·程序员
wno7043 小时前
node.js中使用jquery
前端·node.js·jquery