実践的な開発:Node.jsとMySQLの連携
フロントエンド開発者がバックエンド開発を学ぶには、Node.js と MySQL から始めるのが最適です。
このレッスンでは、Node.js を使って MySQL を操作する方法について解説します。
graph TB
A[Node.js Applications] --> B[mysql2 Driver]
B --> C[Connection Pool]
C --> D[Get the link]
D --> E[Parametric Queries]
E --> F{Operation Type}
F -->|Search| G[execute SELECT]
F -->|Insert| H[execute INSERT]
F -->|Update| I[execute UPDATE]
F -->|Delete| J[execute DELETE]
F -->|Transactions| K[beginTransaction]
K --> L[commit / rollback]
D --> M[Release the connection back to the pool]
1. 学習内容
- mysql2 ドライバのインストールと接続
- コネクションプールの設定
- CRUD操作
- パラメータ化されたクエリ(SQLインジェクションの防止)
- トランザクションのカプセル化
2. 実話
(1) 課題:SQLは学んだものの、プロジェクトでどのように活用すればよいか分からない
SQLを学んだフロントエンド開発者は、Node.jsを使ってバックエンドのコードを書く際に、しばしば途方に暮れてしまいます。SQL文字列を手動で連結するとインジェクション攻撃の標的になりやすく、接続管理が不十分だとデータベース接続が枯渇してしまい、ネストされた非同期コールバックによってコードの保守が困難になるからです。
(2) MySQL 2 以降向けの接続プールとパラメータ化クエリの解決策
mysql2 ドライバー(Promises をサポート)を使用し、接続プール機能で接続を管理し、パラメータ化されたクエリを用いてインジェクション攻撃を防止してください。
| ディメンション | 手動でのSQL構築 | MySQL 2+ 接続プール |
|---|---|---|
| SQLインジェクションのリスク | 極めて高い | ゼロ(パラメータ化されたクエリ) |
| 接続管理 | 非管理型(接続が枯渇する可能性がある) | 自動管理(プール化および再利用) |
| コーディングスタイル | コールバック地獄 | async/await |
| 本番環境対応 | ❌ | ✅ |
3. 設置と接続
▶ 例:mysql2 のインストール
BASH
npm install mysql2
▶ 例:接続の作成
JAVASCRIPT
const mysql = require('mysql2/promise');
async function main() {
const connection = await mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'Root123!',
database: 'mydb'
});
const [rows] = await connection.execute('SELECT VERSION()');
console.log(rows);
await connection.end();
}
main();
4. コネクションプール
JAVASCRIPT
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'Root123!',
database: 'mydb',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
// Querying Using a Connection Pool
const [rows] = await pool.execute('SELECT * FROM users WHERE id = ?', [1]);
5. CRUD操作
▶ 例:データの照会
JAVASCRIPT
// Search All Users
const [users] = await pool.execute('SELECT * FROM users');
// Conditional Query
const [user] = await pool.execute(
'SELECT * FROM users WHERE id = ?',
[userId]
);
▶ 例:データの挿入
JAVASCRIPT
const [result] = await pool.execute(
'INSERT INTO users (username, email) VALUES (?, ?)',
['alice', 'alice@email.com']
);
console.log(result.insertId);
▶ 例:データの更新
JAVASCRIPT
const [result] = await pool.execute(
'UPDATE users SET email = ? WHERE id = ?',
['new@email.com', 1]
);
console.log(result.affectedRows);
▶ 例:データの削除
JAVASCRIPT
const [result] = await pool.execute(
'DELETE FROM users WHERE id = ?',
[1]
);
console.log(result.affectedRows);
6. SQLインジェクションの防止
(1) エラー:文字列の連結
JAVASCRIPT
// Danger! SQL injection
const sql = `SELECT * FROM users WHERE username = '${username}'`;
(2) 正解:パラメータ化されたクエリ
JAVASCRIPT
// Safe: Parameterized query
const [rows] = await pool.execute(
'SELECT * FROM users WHERE username = ?',
[username]
);
7. トランザクションのカプセル化
JAVASCRIPT
async function transfer(fromId, toId, amount) {
const conn = await pool.getConnection();
try {
await conn.beginTransaction();
await conn.execute(
'UPDATE accounts SET balance = balance - ? WHERE id = ?',
[amount, fromId]
);
await conn.execute(
'UPDATE accounts SET balance = balance + ? WHERE id = ?',
[amount, toId]
);
await conn.commit();
return { success: true };
} catch (error) {
await conn.rollback();
return { success: false, error: error.message };
} finally {
conn.release();
}
}
8. ORMの概要
| ORM | 説明 |
|---|---|
| Sequelize | 充実した機能を備えた老舗のORM |
| Prisma | 次世代の型ベースのセキュリティ |
| TypeORM | TypeScriptへの優れた対応 |
| Knex.js | クエリビルダー |
JAVASCRIPT
// Prisma Example
const users = await prisma.user.findMany({
where: { status: 'active' },
include: { orders: true }
});
❓ よくある質問
Q mysql と mysql2 のどちらを使うべきですか?
A mysql2 をお勧めします(Promises をサポートしており、パフォーマンスも優れています)。
Q 接続プールのサイズはどのように設定すべきですか?
A 通常は10~20ですが、同時接続数に応じて調整します。
Q ORMはどのような場合に使うべきですか?
A 複雑なプロジェクトでは開発を簡略化するためにORMを使用し、単純なプロジェクトでは柔軟性を高めるためにネイティブSQLを使用します。
Q mysql と mysql2 の違いは何ですか?
A mysql はコールバックのみをサポートする旧式のドライバーですが、mysql2 は Promise をサポートし、パフォーマンスも向上しています。mysql2 の使用をお勧めします。
Q 接続プールのサイズはどう設定すべきですか?
A 計算式は「CPUコア数 × 2 + ディスク数」です。一般的なWebアプリケーションの場合、10~20で十分です。
📖 まとめ
- mysql2 は、Promises をサポートする Node.js 用の MySQL ドライバーです
- 接続プールは、接続を再利用することでパフォーマンスを向上させます
- パラメータ化されたクエリ によるSQLインジェクションの防止
- トランザクションはデータの整合性を確保します
- ORM はデータベース操作を簡素化します
📝 練習問題
-
基本問題(難易度:⭐):Node.js を使用して MySQL に接続し、データベースをクエリして、ユーザーの一覧を出力してください。
-
上級演習(難易度:⭐⭐):完全なCRUD API(作成、読み取り、更新、削除)を実装してください。
-
課題(難易度:⭐⭐⭐):取引やエラー処理を含む、資金移動機能を実装してください。



