在桌面應用中,SQLite因其輕量、嵌入式特性成為本地存儲的熱門選擇。但若重復初始化數據庫,會導致數據覆蓋或冗余。本文將詳解如何讓Electron應用僅在首次啟動時創建SQLite數據庫,后續啟動直接連接現有庫。
一、核心邏輯與實現原理
核心思路:通過檢測數據庫文件是否存在,決定是否執行建表操作。
關鍵技術點:
- 路徑管理:使用Electron的
app.getPath('userData')
獲取用戶數據目錄,確保數據庫文件持久化存儲。 - 文件存在性檢查:通過Node.js的
fs.existsSync()
判斷數據庫文件是否已創建。 - 條件化初始化:僅當文件不存在時,執行建表SQL語句。
二、分步實現代碼
以下以主進程(main.js
)為例,整合sqlite3
和path
模塊:
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const fs = require('fs');
const sqlite3 = require('sqlite3').verbose();function createWindow() {// 窗口創建邏輯
}app.whenReady().then(() => {// 定義數據庫路徑(用戶數據目錄下)const userDataPath = app.getPath('userData');const dbPath = path.join(userDataPath, 'app_database.db');// 關鍵邏輯:僅在文件不存在時初始化數據庫if (!fs.existsSync(dbPath)) {const db = new sqlite3.Database(dbPath, (err) => {if (err) console.error('Database creation failed:', err);else {// 執行建表語句db.run(`CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,email TEXT UNIQUE)`, (err) => {if (err) console.error('Table creation error:', err);else console.log('Database & tables initialized!');});}});} else {console.log('Existing database connected.');}createWindow();
});
三、關鍵優化與注意事項
- 避免重復初始化
- 使用
CREATE TABLE IF NOT EXISTS
代替CREATE TABLE
,防止后續運行時誤刪表。
- 使用
- 異步安全
- 數據庫操作需封裝在
app.whenReady()
內,確保Electron初始化完成后再訪問文件系統。
- 數據庫操作需封裝在
- 路徑動態生成
- 開發環境與生產環境的路徑差異需通過
app.isPackaged
區分。
- 開發環境與生產環境的路徑差異需通過
- 錯誤處理
- 封裝Promise或
try/catch
捕獲文件操作及SQL執行異常。
- 封裝Promise或
四、進階場景:封裝為可復用模塊
將數據庫邏輯獨立為database.js
模塊:
// database.js
const initDatabase = () => {const dbPath = path.join(app.getPath('userData'), 'app.db');if (!fs.existsSync(dbPath)) {const db = new sqlite3.Database(dbPath);db.exec(`CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);INSERT INTO settings (key, value) VALUES ('first_run', 'true');`);return db;}return new sqlite3.Database(dbPath); // 返回現有連接
};module.exports = { initDatabase };
主進程中調用:
const { initDatabase } = require('./database');
app.whenReady().then(() => {const db = initDatabase();// 其他邏輯
});
五、常見問題排查
問題 | 解決方案 |
---|---|
安裝sqlite3 編譯失敗 | 添加electron-rebuild 并指定target版本 |
打包后數據庫文件未生成 | 在package.json 中配置extraResources 拷貝初始文件 |
渲染進程無法訪問數據庫 | 通過ipcMain 暴露接口,禁止直接跨進程操作 |
六、替代方案對比
方案 | 適用場景 | 缺點 |
---|---|---|
SQLite | 需復雜查詢、事務支持 | 需處理原生模塊編譯 |
JSON文件存儲 | 簡單鍵值對、低數據量 | 性能差,無SQL能力 |
Browser IndexedDB | 純前端存儲,無Node依賴 | 容量限制,無復雜查詢 |