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