【node.js】expressにてmysqlを使う方法メモ
はじめに
今回やりたかったことは以下
・expressからmysqlへクエリ実行
・ormは使わずsqlを直接実行したい
・dbの処理部分は共通化したい
・エラー処理も実装する
node-mysqlというライブラリを使いました
実装
ファイル構成
├── app.js ├── db.js # dbの共通処理はココにまとめる ├── controllers # コントローラはココに │ ├── login.js │ ・・・ ├── models # db処理はココに │ ├── user.js │ ・・・
共通処理を実装(db.js)
とりあえずselectとinsertのsqlを実行できるようにしておく
models以下の各クラスからこのクラスのメソッドを呼び出す
var mysql = require("mysql"); module.exports = { conn: null, // MySQLへ接続 connect: function() { this.conn = mysql.createConnection({ "host": "db_hostname", "user": "db_username", "password": "db_password", "database": "db_name" }); this.conn.connect(function(err) { if (err) { // MySQLへ接続失敗 } else { // MySQLへ接続成功 } }); }, // 1件取得用メソッド getOne: function(query, params, callback) { this.conn.query(query, params, function(err, rows) { if (err) throw new Error(); else callback(rows.length < 1 ? null : rows[0]); }); }, // 複数件取得用メソッド getAll: function(query, params, callback) { this.conn.query(query, params, function(err, rows) { if (err) throw new Error(); else callback(rows); }); }, // insert実行用メソッド insert: function(table, data, callback) { this.conn.query("insert into " + table + " set ?", data, function(err, result, fields) { if (err) throw new Error(); else callback(result.insertId); }); } }
modelの実装(models/user.js)
引数でcallbackを渡す形で実装しましたが、アプリが複雑になっていくとコールバック地獄なるものになるそうです・・・
なので、ここはPromiseを返すようにした方が良さそうだけど今回は話がそれるのでcallbackにしておきます
var db = require("../db.js"); module.exports = { // emailでusersテーブルを検索する getByEmail: function(email) { return new Promise(function(resolve, reject) { var query = "select * from users where email = ?"; db.getOne(query, [email], function(row) { resolve(row); }); }); }, // usersテーブルへinsertする register: function(data) { return new Promise(function(resolve, reject) { db.insert("users", data, function(id) { resolve(id); }); }); }, }
controllerの実装(controllers/login.js)
var express = require("express"); var user = require("../models/user.js"); module.exports = function() { var router = express.Router(); router.get("/", function(req, res, next) { user.getByEmail(req.query.email) .then(function(row) { if (row) { // 成功(jsonを返すなど) } else { // 失敗(jsonを返すなど) } } }); return router; };
こんな感じでやりたいことはだいたい実装できました。
ただ、これだとdb.jsでエラーがあった場合に例外を投げてる箇所で以下のようなエラーで落ちてしまいました
/var/www/html/example.com/public/node_modules/mysql/lib/protocol/Parser.js:78 throw err; // Rethrow non-MySQL errors ^ Error at Query._callback (/var/www/html/example.com/public/db.js:28:9) at Query.Sequence.end (/var/www/html/example.com/public/node_modules/mysql/lib/protocol/sequences/Sequence.js:85:24) at Query.ErrorPacket (/var/www/html/example.com/public/node_modules/mysql/lib/protocol/sequences/Query.js:94:8) at Protocol._parsePacket (/var/www/html/example.com/public/node_modules/mysql/lib/protocol/Protocol.js:280:23) at Parser.write (/var/www/html/example.com/public/node_modules/mysql/lib/protocol/Parser.js:74:12) at Protocol.write (/var/www/html/example.com/public/node_modules/mysql/lib/protocol/Protocol.js:39:16) at Socket.<anonymous> (/var/www/html/example.com/public/node_modules/mysql/lib/Connection.js:109:28) at Socket.emit (events.js:107:17) at readableAddChunk (_stream_readable.js:163:16) at Socket.Readable.push (_stream_readable.js:126:10)
で、非同期処理の中で例外を投げるとエラーになるそうで、express-domain-middlewareを使うことで回避できました。
app.js
var domain = require('express-domain-middleware'); app.use(domain);
この2行を追加すればokでした
以上です