Files
ai-showcase-platform/lib/database-service-base.ts

329 lines
9.2 KiB
TypeScript

// =====================================================
// 資料庫服務基類 - 確保連線正確關閉
// =====================================================
import { db } from './database';
import { PoolConnection } from 'mysql2/promise';
export abstract class DatabaseServiceBase {
// 靜態安全查詢方法 - 每次查詢完就完全關閉連線
static async safeQuery<T = any>(sql: string, params?: any[]): Promise<T[]> {
let connection: PoolConnection | null = null;
try {
// 獲取連線
connection = await db.getConnection();
// 執行查詢
const [rows] = await connection.execute(sql, params);
// 完全關閉連線(不是釋放回連線池)
await connection.destroy();
connection = null;
console.log('✅ 靜態查詢連線已完全關閉');
return rows as T[];
} catch (error) {
// 確保連線被關閉
if (connection) {
try {
await connection.destroy();
} catch (destroyError) {
console.error('關閉靜態查詢連線時發生錯誤:', destroyError);
}
}
throw error;
}
}
// 實例安全查詢方法 - 每次查詢完就完全關閉連線
protected async safeQuery<T = any>(sql: string, params?: any[]): Promise<T[]> {
let connection: PoolConnection | null = null;
try {
// 獲取連線
connection = await db.getConnection();
// 執行查詢
const [rows] = await connection.execute(sql, params);
// 完全關閉連線(不是釋放回連線池)
await connection.destroy();
connection = null;
console.log('✅ 連線已完全關閉');
return rows as T[];
} catch (error) {
// 確保連線被關閉
if (connection) {
try {
await connection.destroy();
} catch (destroyError) {
console.error('關閉連線時發生錯誤:', destroyError);
}
}
throw error;
}
}
// 靜態安全單一查詢方法
static async safeQueryOne<T = any>(sql: string, params?: any[]): Promise<T | null> {
const results = await DatabaseServiceBase.safeQuery<T>(sql, params);
return results.length > 0 ? results[0] : null;
}
// 實例安全單一查詢方法
protected async safeQueryOne<T = any>(sql: string, params?: any[]): Promise<T | null> {
const results = await this.safeQuery<T>(sql, params);
return results.length > 0 ? results[0] : null;
}
// 靜態安全插入方法 - 每次查詢完就完全關閉連線
static async safeInsert(sql: string, params?: any[]): Promise<any> {
let connection: PoolConnection | null = null;
try {
connection = await db.getConnection();
const [result] = await connection.execute(sql, params);
// 完全關閉連線
await connection.destroy();
connection = null;
console.log('✅ 靜態插入連線已完全關閉');
return result;
} catch (error) {
if (connection) {
try {
await connection.destroy();
} catch (destroyError) {
console.error('關閉靜態插入連線時發生錯誤:', destroyError);
}
}
throw error;
}
}
// 實例安全插入方法 - 每次查詢完就完全關閉連線
protected async safeInsert(sql: string, params?: any[]): Promise<any> {
let connection: PoolConnection | null = null;
try {
connection = await db.getConnection();
const [result] = await connection.execute(sql, params);
// 完全關閉連線
await connection.destroy();
connection = null;
console.log('✅ 實例插入連線已完全關閉');
return result;
} catch (error) {
if (connection) {
try {
await connection.destroy();
} catch (destroyError) {
console.error('關閉實例插入連線時發生錯誤:', destroyError);
}
}
throw error;
}
}
// 靜態安全更新方法 - 每次查詢完就完全關閉連線
static async safeUpdate(sql: string, params?: any[]): Promise<any> {
let connection: PoolConnection | null = null;
try {
connection = await db.getConnection();
const [result] = await connection.execute(sql, params);
// 完全關閉連線
await connection.destroy();
connection = null;
console.log('✅ 靜態更新連線已完全關閉');
return result;
} catch (error) {
if (connection) {
try {
await connection.destroy();
} catch (destroyError) {
console.error('關閉靜態更新連線時發生錯誤:', destroyError);
}
}
throw error;
}
}
// 實例安全更新方法 - 每次查詢完就完全關閉連線
protected async safeUpdate(sql: string, params?: any[]): Promise<any> {
let connection: PoolConnection | null = null;
try {
connection = await db.getConnection();
const [result] = await connection.execute(sql, params);
// 完全關閉連線
await connection.destroy();
connection = null;
console.log('✅ 實例更新連線已完全關閉');
return result;
} catch (error) {
if (connection) {
try {
await connection.destroy();
} catch (destroyError) {
console.error('關閉實例更新連線時發生錯誤:', destroyError);
}
}
throw error;
}
}
// 靜態安全刪除方法 - 每次查詢完就完全關閉連線
static async safeDelete(sql: string, params?: any[]): Promise<any> {
let connection: PoolConnection | null = null;
try {
connection = await db.getConnection();
const [result] = await connection.execute(sql, params);
// 完全關閉連線
await connection.destroy();
connection = null;
console.log('✅ 靜態刪除連線已完全關閉');
return result;
} catch (error) {
if (connection) {
try {
await connection.destroy();
} catch (destroyError) {
console.error('關閉靜態刪除連線時發生錯誤:', destroyError);
}
}
throw error;
}
}
// 實例安全刪除方法 - 每次查詢完就完全關閉連線
protected async safeDelete(sql: string, params?: any[]): Promise<any> {
let connection: PoolConnection | null = null;
try {
connection = await db.getConnection();
const [result] = await connection.execute(sql, params);
// 完全關閉連線
await connection.destroy();
connection = null;
console.log('✅ 實例刪除連線已完全關閉');
return result;
} catch (error) {
if (connection) {
try {
await connection.destroy();
} catch (destroyError) {
console.error('關閉實例刪除連線時發生錯誤:', destroyError);
}
}
throw error;
}
}
// 事務處理方法 - 每次查詢完就完全關閉連線
protected async withTransaction<T>(
callback: (connection: PoolConnection) => Promise<T>
): Promise<T> {
let connection: PoolConnection | null = null;
try {
connection = await db.getConnection();
await connection.beginTransaction();
const result = await callback(connection);
await connection.commit();
// 完全關閉連線
await connection.destroy();
connection = null;
console.log('✅ 事務連線已完全關閉');
return result;
} catch (error) {
if (connection) {
try {
await connection.rollback();
} catch (rollbackError) {
console.error('回滾事務時發生錯誤:', rollbackError);
}
try {
await connection.destroy();
} catch (destroyError) {
console.error('關閉事務連線時發生錯誤:', destroyError);
}
}
throw error;
}
}
// 批次查詢方法 - 每次查詢完就完全關閉連線
protected async batchQuery<T = any>(
queries: Array<{ sql: string; params?: any[] }>
): Promise<T[][]> {
let connection: PoolConnection | null = null;
try {
connection = await db.getConnection();
const results: T[][] = [];
for (const query of queries) {
const [rows] = await connection.execute(query.sql, query.params);
results.push(rows as T[]);
}
// 完全關閉連線
await connection.destroy();
connection = null;
console.log('✅ 批次查詢連線已完全關閉');
return results;
} catch (error) {
if (connection) {
try {
await connection.destroy();
} catch (destroyError) {
console.error('關閉批次查詢連線時發生錯誤:', destroyError);
}
}
throw error;
}
}
// 連線健康檢查
protected async checkConnectionHealth(): Promise<boolean> {
try {
await this.safeQueryOne('SELECT 1 as health_check');
return true;
} catch (error) {
console.error('資料庫連線健康檢查失敗:', error);
return false;
}
}
}