Node.js数据库钩子的使用

 更新时间:2023年05月26日 15:54:40   作者:Brett Hoyer  
本文主要介绍了Node.js数据库钩子的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在本文中,我将解释如何在您的Node.js应用程序中使用数据库钩子来解决在开发过程中可能出现的特定问题。

许多应用程序只需要在服务器、数据库之间建立连接池并执行查询。然而,根据您的应用程序和数据库部署情况,可能需要进行其他配置。

例如,多区域分布式SQL数据库可以根据应用程序用例的不同拓扑进行部署。某些拓扑需要在每个会话中在数据库上设置属性。

让我们探索一下Node.js生态系统中一些最受欢迎的数据库客户端和ORM提供的一些钩子。

基础

在使用最流行的关系数据库时,Node.js社区有许多可供选择的驱动程序。在这里,我将重点关注与兼容PostgreSQL的数据库客户端,它们可以用于连接到YugabyteDB或其他PostgreSQL数据库。
Sequelize、Prisma、Knex和node-postgres是一些功能各异的受欢迎的客户端,具体取决于您的需求。我鼓励您阅读它们的文档,以确定哪个最适合您的需求。
这些客户端提供了不同用例的钩子。例如:

  • 连接钩子: 在连接和断开与数据库的连接之前或之后立即执行函数。 
  • 日志钩子: 在不同的日志级别下将消息记录到stdout。 
  • 生命周期钩子: 在对数据库进行调用之前或之后立即执行函数。 

在本文中,我将介绍这些客户端提供的一些钩子,并说明您如何在分布式SQL应用程序中使用它们的好处。

我还将演示如何在创建用户之前使用钩子对用户的密码进行散列,并在连接到具有读副本的多区域数据库后如何设置运行时配置参数。

Sequelize

Sequelize ORM提供了许多钩子来管理数据库事务的整个生命周期。

beforeCreate生命周期钩子可用于在创建新用户之前对密码进行散列处理:

User.beforeCreate(async (user, options) => {
 const hashedPassword = await hashPassword(user.password);
 user.password = hashedPassword;
});

接下来,我使用afterConnect连接钩子来设置会话参数。

通过这个YugabyteDB部署,您可以从跟随者执行读取操作以减少延迟,并且无需从主集群节点读取:

const config = {
  host: process.env.DB_HOST,
  port: 5433,
  dialect: "postgres",
  dialectOptions: {
    ssl: {
      require: true,
      rejectUnauthorized: true,
      ca: [CERTIFICATE],
    },
  },
  pool: {
    max: 5,
    min: 1,
    acquire: 30000,
    idle: 10000,
  },
  hooks: {
     async afterConnect(connection) {
       if (process.env.DB_DEPLOYMENT_TYPE === "multi_region_with_read_replicas") {
         await connection.query("set yb_read_from_followers = true; set session characteristics as transaction read only;");
       }
     },
   },
};
const connection = new Sequelize(
   process.env.DATABASE_NAME,
   process.env.DATABASE_USER,
   process.env.DATABASE_PASSWORD,
   config
);

通过使用这个钩子,在连接池中的每个数据库会话在建立新连接时都会设置这些参数:

  • set yb_read_from_followers = true;:此参数控制是否启用从跟随者读取。
  • set session characteristics as transaction read only;:此参数将只读设置应用于后续的所有语句和事务块。 

Prisma

尽管在Node.js社区中,Prisma是许多人首选的ORM,但在撰写本文时,Prisma并不包含Sequelize中的许多内置钩子。目前,该库包含用于处理查询生命周期、日志记录和断开连接的钩子,但在建立连接之前或之后提供的帮助很少。

以下是如何使用Prisma的生命周期中间件在创建用户之前对密码进行哈希处理的方法:

prisma.$use(async (params, next) => {
 if (params.model == 'User' && params.action == 'create') {
   params.args.data.password = await hashPassword(params.args.data.password);
 }
 return next(params)
})
const create = await prisma.user.create({
 data: {
   username: 'bhoyer',
   password: 'abc123'
 },
})

要设置会话参数以利用我们的读取副本,我们需要在查询数据库之前执行一条语句:

await prisma.$executeRaw(`set yb_read_from_followers = true; set session characteristics as transaction read only;`);
const users = await prisma.user.findMany();

如果您需要立即在连接池中建立连接以设置参数,您可以使用Prisma显式地进行连接,而不使用连接池的延迟连接。

Prisma具有查询(query)、错误(error)、信息(info)和警告(warn)等日志级别。可以使用基于事件的日志记录来处理查询事件:

const prisma = new PrismaClient({
 log: [
   {
     emit: 'event',
     level: 'query',
   },
   {
     emit: 'stdout',
     level: 'error',
   },
   {
     emit: 'stdout',
     level: 'info',
   },
   {
     emit: 'stdout',
     level: 'warn',
   },
 ],
});

prisma.$on('query', (e) => {
 console.log('Query: ' + e.query);
 console.log('Params: ' + e.params);
 console.log('Duration: ' + e.duration + 'ms');
});

这在开发过程中对于在分布式系统中进行查询调优非常有帮助。
下面是如何在退出之前使用beforeExit钩子来访问数据库的示例:​​​​​​​

const prisma = new PrismaClient();
prisma.$on('beforeExit', async () => {
 // PrismaClient still available
 await prisma.issue.create({
   data: {
     message: 'Connection exiting.' 
   },
 })
});

Knex是一个轻量级的查询构建器,但它没有更全功能的ORM中的查询中间件。
要对密码进行哈希处理,可以使用自定义函数来手动处理:

async function handlePassword(password) {
  const hashedPassword = await hashPassword(password);
  return hashedPassword;
}
const password = await handlePassword(params.password);
knex('users').insert({...params, password});

在Knex.js查询构建器中实现连接钩子所需的语法与Sequelize类似。以下是如何设置会话参数以从YugabyteDB的副本节点读取的示例代码:

const knex = require('knex')({
  client: 'pg',
  connection: {/*...*/},
  pool: {
    afterCreate: function (connection, done) {
      connection.query('set yb_read_from_followers = true; set session characteristics as transaction read only;', function (err) {
        if (err) {
          //Query failed
          done(err, conn);
        } else {
          console.log("Reading from replicas.");
       done();
        }
      });
    }
  }
});

node-postgres库是所有讨论过的库中最低级的库。在底层,使用Node.js的EventEmitter来触发连接事件。

当在连接池中建立新连接时,会触发connect事件。我们可以使用它来设置我们的会话参数。我还添加了一个错误钩子来捕获和记录所有错误消息的示例代码:​​​​​​​

const config = {
  user: process.env.DB_USER,
  host: process.env.DB_HOST,
  password: process.env.DB_PASSWORD,
  port: 5433,
  database: process.env.DB_NAME,
  min: 1,
  max: 10,
  idleTimeoutMillis: 5000,
  connectionTimeoutMillis: 5000,
  ssl: {
    rejectUnauthorized: true,
    ca: [CERTIFICATE],
    servername: process.env.DB_HOST,
  }
};
const pool = new Pool(config);
pool.on("connect", (c) => {
  c.query("set yb_read_from_followers = true; set session characteristics as transaction read only;");
});
pool.on("error", (e) => {
  console.log("Connection error: ", e);
});

在node-postgres中,我们没有可用的生命周期钩子,所以像Prisma一样,我们必须手动进行密码哈希处理:

async function handlePassword(password) {
  const hashedPassword = await hashPassword(password);
  return hashedPassword;
}
const password = await handlePassword(params.password);
const user = await pool.query('INSERT INTO user(username, password) VALUES ($1, $2) RETURNING *', [params.username, password]);

总结

正如你所看到的,钩子可以解决之前由复杂且容易出错的应用程序代码所引起的许多问题。每个应用程序都有不同的要求和面临新的挑战。在你的开发过程中,可能会经过很多年才需要使用特定的钩子,但现在,当那一天来临时,请准备就绪。

到此这篇关于Node.js数据库钩子的使用的文章就介绍到这了,更多相关Node.js数据库钩子内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解node.js创建一个web服务器(Server)的详细步骤

    详解node.js创建一个web服务器(Server)的详细步骤

    这篇文章主要介绍了详解node.js创建一个web服务器(Server)的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • Node.JS中的模块、exports和module讲解

    Node.JS中的模块、exports和module讲解

    这篇文章主要介绍了Node.JS中的模块、exports和module讲解,模块分为两类一类是核心模块一类是文件模块,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • 用Node写一条配置环境的指令

    用Node写一条配置环境的指令

    这篇文章主要介绍了用Node写一条配置环境的指令,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • node内存泄漏排查与修复过程

    node内存泄漏排查与修复过程

    之前开发了一个node接口,该接口使用canvas绘制产品图提供给java端使用,在运行了一段时间后发现了内存泄漏问题,本文浅记下修复过程,文章通过图文介绍的非常详细,需要的朋友可以参考下
    2024-06-06
  • 如何在node.js中使用​JsonWebToken模块进行token加密

    如何在node.js中使用​JsonWebToken模块进行token加密

    目前在web框架中最流行的身份验证是使用jsonwebtoken,简称jwt.可以设置加密方式,过期时间,存放个人信息,逆解析,下面这篇文章主要给大家介绍了关于如何在node.js中使用​JsonWebToken模块进行token加密的相关资料,需要的朋友可以参考下
    2023-03-03
  • Nodejs高扩展性的模板引擎 functmpl简介

    Nodejs高扩展性的模板引擎 functmpl简介

    本文给大家分享的是一款nodejs高扩展性的模板引擎functmpl的简单介绍以及用法详解,有需要的小伙伴可以参考下
    2017-02-02
  • Windows系统下使用Sublime搭建nodejs环境

    Windows系统下使用Sublime搭建nodejs环境

    最近在研究Nodejs开发,俗话说,工欲善其事,必先利其器,当然要找到一款用着顺手的编辑器作为开始。这里我们选择的是Sublime Text 3,除了漂亮的用户界面,最吸引我的就是它的插件扩展功能以及跨平台特性。
    2015-04-04
  • 深入理解Node中的buffer模块

    深入理解Node中的buffer模块

    本篇文章主要介绍了Node中的buffer,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Nodejs中Express 常用中间件 body-parser 实现解析

    Nodejs中Express 常用中间件 body-parser 实现解析

    这篇文章主要介绍了Nodejs中Express 常用中间件 body-parser 实现解析,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • node.js express和koa中间件机制和错误处理机制

    node.js express和koa中间件机制和错误处理机制

    这篇文章主要介绍了node.js express和koa中间件机制和错误处理机制,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-07-07

最新评论