Electron实现“仅首次运行时创建SQLite数据库”

发布于:2025-07-17 ⋅ 阅读:(25) ⋅ 点赞:(0)

在桌面应用中,SQLite因其轻量、嵌入式特性成为本地存储的热门选择。但若重复初始化数据库,会导致数据覆盖或冗余。本文将详解如何让Electron应用仅在首次启动时创建SQLite数据库,后续启动直接连接现有库。


一、核心逻辑与实现原理

核心思路:通过检测数据库文件是否存在,决定是否执行建表操作。
关键技术点

  1. 路径管理:使用Electron的app.getPath('userData')获取用户数据目录,确保数据库文件持久化存储。
  2. 文件存在性检查:通过Node.js的fs.existsSync()判断数据库文件是否已创建。
  3. 条件化初始化:仅当文件不存在时,执行建表SQL语句。

二、分步实现代码

以下以主进程(main.js)为例,整合sqlite3path模块:

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();
});

三、关键优化与注意事项
  1. 避免重复初始化
    • 使用CREATE TABLE IF NOT EXISTS代替CREATE TABLE,防止后续运行时误删表。
  2. 异步安全
    • 数据库操作需封装在app.whenReady()内,确保Electron初始化完成后再访问文件系统。
  3. 路径动态生成
    • 开发环境与生产环境的路径差异需通过app.isPackaged区分。
  4. 错误处理
    • 封装Promise或try/catch捕获文件操作及SQL执行异常。

四、进阶场景:封装为可复用模块

将数据库逻辑独立为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依赖 容量限制,无复杂查询

网站公告

今日签到

点亮在社区的每一天
去签到