TypeORM のメソッドそのままでDBに接続すると状態管理がごちゃっとするので、ラッパークラスを作って、そこでコネクションの管理を行うようにしていきます。
コネクション管理用のクラスを作成する
-
get()
でConnection
が取得できる -
get()
を呼び出した時にコネクションが開いて場合は、同時に作成する -
close()
でConnection
を閉じる -
close()
を呼び出した時にコネクションが閉じていた場合は、何もせず、エラーも起こさない
dbconnection.ts
import {
Connection,
createConnection,
EntityManager,
getConnection,
ConnectionOptions,
} from 'typeorm';
export class DBConnection {
private static con?: Connection;
static getManager = (): Promise<EntityManager> =>
DBConnection.get().then(con => con.manager);
static get = async (): Promise<Connection> => {
if (DBConnection.con && DBConnection.con.isConnected)
return DBConnection.con;
if (DBConnection.con instanceof Connection)
return DBConnection.con.connect();
return DBConnection.create();
};
private static create = async (): Promise<Connection> => {
DBConnection.con = await createConnection(DBConnection.options).catch(() =>
getConnection(),
);
if (!DBConnection.con.isConnected) await DBConnection.con.connect();
return DBConnection.con;
};
static close = async (): Promise<void> => {
if (!DBConnection.con) return;
if (DBConnection.con && DBConnection.con.isConnected)
DBConnection.con.close();
DBConnection.con = undefined;
};
}
export namespace DBConnection {
export const options: ConnectionOptions = {
type: 'postgres',
host: process.env.DB_HOST,
port: Number.parseInt(process.env.DB_PORT!),
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE_NAME,
synchronize: false,
logging: process.env.NODE_ENV === 'production' ? ['error'] : 'all',
};
}
テスト
dbconnection.spec.ts
import { Connection, EntityManager } from 'typeorm';
import { DBConnection } from 'src/infrastructure/dbconnection';
describe('DBConnection', () => {
let connection: Connection;
beforeEach(async () => {
connection = await DBConnection.get();
});
it('should be defined', () => {
expect(connection).toBeDefined();
});
it('isConnected', () => {
expect(connection.name).toBe('default');
expect(connection.isConnected).toBeTruthy();
});
it('isConnected2', () => {
expect(connection.name).toBe('default');
expect(connection.isConnected).toBeTruthy();
});
it('close', async () => {
await DBConnection.close();
});
it('getManager', async () => {
const manager = await DBConnection.getManager();
expect(manager instanceof EntityManager).toBeTruthy();
});
afterEach(async () => {
await DBConnection.close();
});
});
使ってみる
あとは通常通り Connection をつかってなんやかんや
import { Connection } from 'typeorm';
const connection: Connection = await DBConnection.get();
const result: Promise<any> = connection.transaction(manager => {
return manager.query(`select * from users;`);
});
最後に
TypeORM の createConnection 等のメソッドが他のところからも勝手に呼べしまうのが難点。
何か制限をかけられる方法をご存知の方がいれば教えていただきたいですm(_ _)m