【问题标题】:How to provide a mysql database connection in single file in nodejs如何在nodejs的单个文件中提供mysql数据库连接
【发布时间】: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 连接。

【问题讨论】:

    标签: mysql node.js express node-modules


    【解决方案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://stackoverflow.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 });
                }
            });
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-02-08
              • 2012-10-19
              • 1970-01-01
              • 2019-08-21
              • 2016-03-01
              • 1970-01-01
              • 1970-01-01
              • 2019-03-05
              相关资源
              最近更新 更多