【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でした
以上です