
graphql 解析器返回 null 的常见原因是数据库查询结果结构与 graphql 类型定义不匹配,例如误将数组整体返回给非列表类型字段,应明确返回单个对象(如 result[0])。
graphql 解析器返回 null 的常见原因是数据库查询结果结构与 graphql 类型定义不匹配,例如误将数组整体返回给非列表类型字段,应明确返回单个对象(如 result[0])。
在使用 MySQL 与 GraphQL 集成时,一个典型陷阱是:AccountType 被定义为单个对象类型(非 GraphQLList),但 MySQL 查询(如 SELECT ... WHERE)默认返回的是行数组(即使只匹配一条记录,result 也是形如 [ { id: 1, email: 'a@b.com', ... } ] 的数组)。若解析器直接 resolve(result),GraphQL 会因类型不兼容而静默返回 null——即使 console.log(result) 看似有值。
问题根源在于 queries.js 中的 login 函数:
login: (email, password) => {
return new Promise((resolve) => {
const account = `SELECT id, email, phone, password FROM accounts WHERE email=? AND password=?`;
db.query(account, [email, password], (err, result) => {
if (err) throw err;
// ❌ 错误:resolve(result) → 返回数组,但 AccountType 期望单个对象
// ✅ 正确:resolve(result[0] || null) → 明确提取首项或 null
resolve(result[0] || null);
});
});
}
关键修复点:
- 将
resolve(result)改为resolve(result[0] || null),确保返回值严格符合AccountType的单对象语义; -
强烈建议使用参数化查询(
?占位符)替代字符串拼接,避免 SQL 注入(原代码中"${email}"极其危险); - 移除
isEmpty(result[0])的自定义判断(未定义该函数),改用result[0] || null更简洁安全。
此外,Schema.js 中的 resolve 已正确使用 async/await,无需额外包装 Promise,可进一步简化为:
async resolve(parent, args) {
return queries.login(args.email, args.password); // 直接返回 Promise
}
完整最佳实践示例:
// queries.js(修复后)
const connection = require('./connection');
const db = connection.connect();
module.exports = {
login: (email, password) => {
return new Promise((resolve, reject) => {
const sql = 'SELECT id, email, phone, password FROM accounts WHERE email = ? AND password = ?';
db.query(sql, [email, password], (err, results) => {
if (err) return reject(err);
// 返回第一个匹配对象,无匹配则返回 null(GraphQL 自动处理为 null 字段)
resolve(results[0] || null);
});
});
}
};
注意事项总结:
- GraphQL 对象类型(如
AccountType)对应单个 JS 对象,绝不可返回数组; - 使用
GraphQLList(AccountType)才能接收数组,否则必为null; - 始终优先采用参数化查询,杜绝字符串拼接 SQL;
- 在开发阶段启用 GraphQL 的
debug: true选项,有助于捕获类型不匹配的隐式错误。
遵循以上规范,即可确保 MySQL 数据精准映射至 GraphQL Schema,彻底解决“数据可打印却返回 null”的问题。











