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('失败')
})
相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端