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




