如何在nodejs的单个文件中提供mysql数据库连接
Posted
技术标签:
【中文标题】如何在nodejs的单个文件中提供mysql数据库连接【英文标题】:How to provide a mysql database connection in single file in nodejs 【发布时间】:2015-08-13 06:35:28 【问题描述】:我需要为模块提供 mysql 连接。我有这样的代码。
var express = require('express'),
app = express(),
server = require('http').createServer(app);
var mysql = require('mysql');
var connection = mysql.createConnection(
host : '127.0.0.1',
user : 'root',
password : '',
database : 'chat'
);
connection.connect(function(err)
if (err)
console.error('error connecting: ' + err.stack);
return;
);
app.get('/save', function(req,res)
var post = from:'me', to:'you', msg:'hi';
var query = connection.query('INSERT INTO messages SET ?', post, function(err, result)
if (err) throw err;
);
);
server.listen(3000);
但是我们如何为所有模块提供一次 mysql 连接。
【问题讨论】:
【参考方案1】:您可以创建一个 db 包装器然后需要它。节点的 require 每次都返回相同的模块实例,因此您可以执行连接并返回处理程序。来自Node.js docs:
每次调用 require('foo') 都会返回完全相同的对象,如果它会解析到同一个文件。
你可以创建db.js
:
var mysql = require('mysql');
var connection = mysql.createConnection(
host : '127.0.0.1',
user : 'root',
password : '',
database : 'chat'
);
connection.connect(function(err)
if (err) throw err;
);
module.exports = connection;
然后在您的app.js
中,您只需要求它。
var express = require('express');
var app = express();
var db = require('./db');
app.get('/save',function(req,res)
var post = from:'me', to:'you', msg:'hi';
db.query('INSERT INTO messages SET ?', post, function(err, result)
if (err) throw err;
);
);
server.listen(3000);
这种方法允许您抽象任何连接细节,包装您想要公开的任何其他内容,并在整个应用程序中要求db
,同时由于节点要求的工作原理,您可以保持与您的数据库的一个连接:)
【讨论】:
@Sean3z 你确定connection.connect()
不会在每次文件为require
d 时创建连接吗?
我意识到我参加聚会有点晚了,但是将 db.js 文件放在 express 应用程序中的常规位置是什么?
请告诉我,不关闭连接不会消耗很多内存吗?
在 Windows 上,这个约定有一个特殊的情况需要注意: (1) node.js 根据传递给 require() 的字符串缓存导出,并且这个字符串缓存区分大小写; (2) 由于 Windows 路径不区分大小写,因此这实际上会创建 2 个数据库连接实例。只要您的要求语句在所有文件中的大小写相同,就不会成为问题。
连接池比使用单个连接更优化。相同的模式可用于连接池。参考this实现。【参考方案2】:
我采用了与 Sean3z 类似的方法,但每次我进行查询时都会关闭连接。
如果它只在你的应用程序的入口点上执行,他的方法是有效的,但是假设你有想要执行var db = require('./db')
的控制器。您不能这样做,否则每次访问该控制器时,您都将创建一个新连接。
为了避免这种情况,我认为每次都打开和关闭连接会更安全。
这是我的代码的 sn-p。
mysq_query.js
// Dependencies
var mysql = require('mysql'),
config = require("../config");
/*
* @sqlConnection
* Creates the connection, makes the query and close it to avoid concurrency conflicts.
*/
var sqlConnection = function sqlConnection(sql, values, next)
// It means that the values hasnt been passed
if (arguments.length === 2)
next = values;
values = null;
var connection = mysql.createConnection(config.db);
connection.connect(function(err)
if (err !== null)
console.log("[MYSQL] Error connecting to mysql:" + err+'\n');
);
connection.query(sql, values, function(err)
connection.end(); // close the connection
if (err)
throw err;
// Execute the callback
next.apply(this, arguments);
);
module.exports = sqlConnection;
你可以在任何地方使用它
var mysql_query = require('path/to/your/mysql_query');
mysql_query('SELECT * from your_table where ?', id: '1', function(err, rows)
console.log(rows);
);
更新: config.json 看起来像
"db":
"user" : "USERNAME",
"password" : "PASSWORD",
"database" : "DATABASE_NAME",
"socketPath": "/tmp/mysql.sock"
希望这会有所帮助。
【讨论】:
@harshvardhan 我已经在配置信息中更新了它。 我在控制台中收到以下错误:"db": ^ SyntaxError: Unexpected token : 好的,所以我已经在 mysql_query.js 文件本身中设置了 config.json 对象,然后就没有语法问题了。但同样,我在控制台中收到以下错误:[MYSQL] Error connected to mysql:Error: ER_ACCESS_DENIED_ERROR: Access denied for user ''@'localhost' (using password: NO) 我有密码在我的数据库中,当我尝试通过命令行上的相同凭据登录我的 MySQL 数据库时,我通过了它。 @harshvardhan 恐怕现在只是配置问题。尝试查看包的文档。 github.com/mysqljs/mysql【参考方案3】:试试这个
var express = require('express');
var mysql = require('mysql');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded( extended: false ));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next)
var err = new Error('Not Found');
err.status = 404;
next(err);
);
// error handlers
// development error handler
// will print stacktrace
console.log(app);
if (app.get('env') === 'development')
app.use(function(err, req, res, next)
res.status(err.status || 500);
res.render('error',
message: err.message,
error: err
);
);
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next)
res.status(err.status || 500);
res.render('error',
message: err.message,
error:
);
);
var con = mysql.createConnection(
host: "localhost",
user: "root",
password: "admin123",
database: "sitepoint"
);
con.connect(function(err)
if(err)
console.log('Error connecting to Db');
return;
console.log('Connection established');
);
module.exports = app;
【讨论】:
【参考方案4】:从 node.js 文档中,“要让模块多次执行代码、导出函数并调用该函数”,您可以使用 node.js module.export 并使用单个文件来管理数据库连接。您可以在Node.js documentation 找到更多信息。假设 db.js 文件是这样的:
const mysql = require('mysql');
var connection;
module.exports =
dbConnection: function ()
connection = mysql.createConnection(
host: "127.0.0.1",
user: "Your_user",
password: "Your_password",
database: 'Your_bd'
);
connection.connect();
return connection;
;
然后,您要使用连接的文件可能类似于 useDb.js:
const dbConnection = require('./db');
var connection;
function callDb()
try
connection = dbConnectionManager.dbConnection();
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields)
if (!error)
let response = "The solution is: " + results[0].solution;
console.log(response);
else
console.log(error);
);
connection.end();
catch (err)
console.log(err);
【讨论】:
【参考方案5】:var mysql = require('mysql');
var pool = mysql.createPool(
host : 'yourip',
port : 'yourport',
user : 'dbusername',
password : 'dbpwd',
database : 'database schema name',
dateStrings: true,
multipleStatements: true
);
// TODO - if any pool issues need to try this link for connection management
// https://***.com/questions/18496540/node-js-mysql-connection-pooling
module.exports = function(qry, qrytype, msg, callback)
if(qrytype != 'S')
console.log(qry);
pool.getConnection(function(err, connection)
if(err)
if(connection)
connection.release();
throw err;
// Use the connection
connection.query(qry, function (err, results, fields)
connection.release();
if(err)
callback('E#connection.query-Error occurred.#'+ err.sqlMessage);
return;
if(qrytype==='S')
//for Select statement
// setTimeout(function()
callback(results);
// , 500);
else if(qrytype==='N')
let resarr = results[results.length-1];
let newid= '';
if(resarr.length)
newid = resarr[0]['@eid'];
callback(msg + newid);
else if(qrytype==='U')
//let ret = 'I#' + entity + ' updated#Updated rows count: ' + results[1].changedRows;
callback(msg);
else if(qrytype==='D')
//let resarr = results[1].affectedRows;
callback(msg);
);
connection.on('error', function (err)
connection.release();
callback('E#connection.on-Error occurred.#'+ err.sqlMessage);
return;
);
);
【讨论】:
【参考方案6】:我认为您应该使用连接池而不是共享单个连接。连接池会提供更好的性能,您可以查看here。
正如库documentation 中所述,这是因为 MySQL 协议是顺序的(这意味着您需要多个连接来并行执行查询)。
Connection Pool Docs
【讨论】:
【参考方案7】:您可以创建一个全局变量,然后在其他文件中访问该变量。
这是我的代码,我为 MySQL 数据库连接创建了一个名为 db.js 的单独文件
const mysql = require('mysql');
var conn = mysql.createConnection(
host: "localhost",
user: "root",
password: "xxxxx",
database: "test"
);
conn.connect((err) =>
if (err) throw err;
console.log('Connected to the MySql DB');
);
module.exports = conn;
然后在app.js文件中
const express = require('express');
const router = express.Router();
// MySql Db connection and set in globally
global.db = require('../config/db');
现在您可以在任何其他文件中使用它
const express = require('express');
const router = express.Router();
router.post('/signin', (req, res) =>
try
var param = req.body;
var sql = `select * from user`;
// db is global variable
db.query(sql, (err, data) =>
if (err) throw new SyntaxError(err);
res.status(200).json( 'auth': true, 'data': data );
);
catch (err)
res.status(400).json( 'auth': false, 'data': err.message );
);
【讨论】:
以上是关于如何在nodejs的单个文件中提供mysql数据库连接的主要内容,如果未能解决你的问题,请参考以下文章