如何在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() 不会在每次文件为required 时创建连接吗? 我意识到我参加聚会有点晚了,但是将 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数据库连接的主要内容,如果未能解决你的问题,请参考以下文章

如何在nodejs中的单个服务调用中上传和下载文件?

使用 NodeJS 在 MySQL 中运行 SQL 文件

nodejs如何复制mysql数据库

07 nodejs+mysql向外提供api

Twilio - 如何通过在 NodeJs 中提供呼叫 SID 来检索语音呼叫记录媒体文件

NodeJS|Cluster:如何将数据从主服务器发送到所有或单个孩子/工人?