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('失败')
})
相关推荐
coderCN18 分钟前
Nodejs mysql2+express+yaml
node.js
求道於盲22 分钟前
python中的抽象类
前端
Csvn32 分钟前
CSS 层叠与现代布局:BFC、@layer 与 grid/flex 的取舍
前端
烬羽32 分钟前
我把"时间胶囊"部署上腾讯云宝塔,跨域从根源消失了
nginx·node.js·全栈
CodeSheep42 分钟前
OpenJDK 全面禁止 AI 生成代码!
前端·后端·程序员
IT_陈寒1 小时前
为什么我的Vue组件总是莫名其妙重渲染?
前端·人工智能·后端
乘风gg1 小时前
企业级 AI Coding 的 Harness 工程实战:8 个 Skill 串起全链路
前端·ai编程·claude
染指11103 小时前
103.RAG-LLamaIndex后端rag问答-聊天接口
前端·javascript·vue.js·人工智能
东风破_10 小时前
danci 2:创建的单词书到底存在哪里?从 Supabase 一路理解 ORM、Drizzle 和 RLS
数据库·后端·node.js