👌

NodejsでSQLファイル外だしてみた

2024/06/29に公開

1. 内容

  • 本実験の目的は、Node.jsアプリケーションにおいてSQLクエリを外部ファイルとして管理する仕組みを実装し、その効果と利点を検証することです。この手法は、以下のような多くの利点をもたらすと考えられます:

    • コードの分離: ビジネスロジックとデータアクセスロジックを明確に分離することができます。これにより、コードの可読性と保守性が向上します。
    • 再利用性の向上: 同じSQLクエリを複数の場所で使用する場合、外部ファイルとして管理することで簡単に再利用できます。
    • バージョン管理の容易さ: SQLファイルを独立して管理することで、データベーススキーマやクエリの変更履歴を追跡しやすくなります。
    • セキュリティの向上: センシティブなSQLクエリを外部ファイルに保存することで、不正アクセスのリスクを軽減できる可能性があります。
    • パフォーマンスの最適化: 複雑なクエリや頻繁に使用されるクエリを外部ファイルとして管理することで、キャッシュや最適化が容易になります。
    • テストの簡便化: SQLクエリを独立したファイルとして管理することで、データベース操作の単体テストが容易になります。

2. 事前準備

-- テーブルが既に存在する場合は削除
DROP TABLE IF EXISTS employees;

-- employeesテーブルの作成
CREATE TABLE employees (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    position VARCHAR(100) NOT NULL
);

-- サンプルデータの挿入
INSERT INTO employees (name, position) VALUES
    ('John Doe', 'Software Engineer'),
    ('Jane Smith', 'Project Manager'),
    ('Mike Johnson', 'Data Analyst'),
    ('Emily Brown', 'UX Designer'),
    ('David Wilson', 'DevOps Engineer');

3. エンティティクラス

  • TypeScriptは、interfaceやabstract classは、リフレクションが使えないのでクラスにする。
export class Employee {
    id?: number;
    name?: string;
    position?: string;
}

4. リポジトリクラス

  • TypeScriptは、interfaceやabstract classは、リフレクションが使えないのでクラスにする。
  • コーディングするさい型をしっかりするために用意する
import {Employee} from "./Employee";
import {ModelRepository} from "../../repository/ModelRepository";
import {Class, Method, Param} from "../../reflect/ReflectDecorator";

@Class
export class EmployeeRepository implements ModelRepository {

    @Method
    findById(@Param("id") id: number): Promise<Employee> {
        return Promise.reject();
    }

}

5. 実行

import mysql from 'mysql2/promise';
import {PoolOptions} from "mysql2/index";
import {RepositoryManager} from "./repository/RepositoryManager";
import {EmployeeRepository} from "./model/employee/EmployeeRepository";

const pool = mysql.createPool({...});
const manager = new RepositoryManager(pool);

//manager.add("パッケージかフォルダ指定", リポジトリクラス);
manager.add("model.employee", EmployeeRepository);

try {
    const connection = await pool.getConnection();
    console.log('Successfully connected to the database.');
    connection.release();

    // <ジェネリクス>で型を強制
    const employeeRepository = manager.getRepository(EmployeeRepository);

    const employee = await employeeRepository.findById(1);
    if (employee) {
        console.log("Find by ID:", employee.name, employee.position);
    } else {
        console.log("Employee not found");
    }
} catch (error) {
    console.error("Error in main:", error);
} finally {
    await pool.end();
}

6. まとめ

  • このアプローチでは、SQLクエリを外部ファイルに保存し、必要に応じて動的に読み込んでいます。これにより、アプリケーションのコードとSQLロジックを分離し、保守性と再利用性を向上させています。また、TypeScriptを使用することで、型安全性も確保しています。

Discussion