You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Fastify中使用@fastify/mysql编写数据库连接器插件失败:无法读取'mysql'属性

Fastify中使用@fastify/mysql编写数据库连接器插件失败:无法读取'mysql'属性

看起来你遇到的问题核心在于数据库插件的写法以及@fastify/mysql实例的获取方式不对,咱们一步步来解决:

问题根源分析

  • 数据库插件的异步注册未正确等待:在desecuDB.js中,你嵌套调用了fastify.register(require('@fastify/mysql')),但没有用await等待这个注册完成,导致后续路由/控制器调用时,数据库实例还没准备好。
  • 错误的实例获取方式:你尝试用fastify.desecu获取数据库实例,但@fastify/mysql的命名实例需要通过fastify.mysql.get('name')来获取,fastify.desecu这个属性根本不存在,这就是你看到Cannot read properties of undefined (reading 'mysql')的直接原因。

修正步骤

1. 修复数据库连接插件(desecuDB.js)

把插件内部的注册改为异步等待,并且不需要手动调用fastify.ready(Fastify的listen方法会自动等待所有插件加载完成):

const dotenv = require('dotenv');
const fp = require('fastify-plugin');
dotenv.config(); // 也可以让server.js统一加载环境变量,这里加一层也没问题

async function connectToDesecuDB(fastify) {
  // 必须await这个注册,确保mysql插件完全加载完成
  await fastify.register(require('@fastify/mysql'), {
    connectionString: `mysql://${process.env.DB_DESECU_USER}:${process.env.DB_DESECU_PASSWORD}@${process.env.DB_DESECU_HOST}/${process.env.DB_DESECU_DATABASE}`,
    name: 'desecu'
  });

  // 可选:把数据库实例装饰到fastify上,方便后续直接调用
  fastify.decorate('desecuDB', fastify.mysql.get('desecu'));
  
  console.log('Successfully connected to desecu database');
}

module.exports = fp(connectToDesecuDB);

2. 修复模型中的数据库实例获取(desecuModel.js)

现在可以直接用装饰后的fastify.desecuDB,或者用fastify.mysql.get('desecu')来获取实例,同时注意mysql2的query返回值是数组(结果集+字段信息),我们只需要第一个元素:

async function getData(fastify) {
  try {
    // 方式一:用装饰后的属性,更直观
    const db = fastify.desecuDB;
    // 方式二:直接通过mysql插件获取命名实例
    // const db = fastify.mysql.get('desecu');
    
    const [result] = await db.query('SELECT * FROM test');
    return result;
  } catch (error) {
    throw new Error(`Database query failed: ${error.message}`);
  }
}

module.exports = {
  getData,
};

3. 关于项目结构的合理性

你把DB、模型、控制器、路由分开的方式完全符合Fastify的最佳实践,这种分层结构有利于代码的维护和扩展,所以不用担心结构本身的问题,只是插件的写法需要调整。

备注:内容来源于stack exchange,提问作者J.Bon

火山引擎 最新活动