如何让TypeORM适配Ionic 5/6?附SQLite schema变更疑问
Ionic 5/6 本地数据持久化方案:TypeORM 配置与 SQLite Schema 变更管理
一、Ionic 5/6 结合 TypeORM 实现本地设备数据持久化配置
以下是经过验证的实操步骤,适配 Capacitor 环境(Ionic 5/6 主流适配方案):
1. 安装依赖
执行以下命令安装核心依赖及 Capacitor SQLite 驱动:
npm install typeorm reflect-metadata @capacitor/sqlite npx cap sync
同时修改 tsconfig.json,启用 TypeScript 装饰器支持:
{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } }
2. 配置 TypeORM 数据源
在项目根目录创建 data-source.ts,配置数据库连接信息:
import { DataSource } from "typeorm"; import { CapacitorSQLite } from "@capacitor/sqlite"; // 导入自定义实体类,后续步骤定义 import { User } from "./entities/User"; export const AppDataSource = new DataSource({ type: "capacitor", driver: CapacitorSQLite, database: "app_local_db", // 自定义数据库名称 entities: [User], // 所有实体类集合 synchronize: false, // 生产环境必须关闭,避免自动修改 schema migrations: ["src/migrations/**/*.ts"], // 迁移文件路径 logging: false, });
3. 定义实体类
在 src/entities/ 目录下创建实体文件(如 User.ts),用装饰器映射数据库表结构:
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"; @Entity() export class User { @PrimaryGeneratedColumn() id: number; @Column({ nullable: false }) username: string; @Column({ nullable: true }) avatar: string; }
4. 初始化数据源
在 app.component.ts 的初始化逻辑中启动数据源:
import { Component } from '@angular/core'; import { AppDataSource } from './data-source'; @Component({ selector: 'app-root', templateUrl: 'app.component.html', styleUrls: ['app.component.scss'], }) export class AppComponent { constructor() { this.initializeApp(); } async initializeApp() { // 其他初始化逻辑(如平台就绪) try { await AppDataSource.initialize(); console.log('TypeORM 数据源初始化成功'); } catch (error) { console.error('TypeORM 初始化失败:', error); } } }
5. 数据操作示例
创建服务类封装 CRUD 逻辑,以 UserService.ts 为例:
import { Injectable } from '@angular/core'; import { Repository } from 'typeorm'; import { User } from '../entities/User'; import { AppDataSource } from '../data-source'; @Injectable({ providedIn: 'root' }) export class UserService { private userRepo: Repository<User>; constructor() { this.userRepo = AppDataSource.getRepository(User); } async getUsers(): Promise<User[]> { return this.userRepo.find(); } async addUser(user: Omit<User, 'id'>): Promise<User> { return this.userRepo.save(user); } }
关键注意事项
- 开发阶段可临时开启
synchronize: true自动同步实体与表结构,但生产环境必须关闭,改用迁移脚本管理 schema。 - 确保
@capacitor/sqlite与typeorm版本兼容(建议使用最新稳定版)。
二、SQLite Schema 变更管理方案
如果继续使用原生 SQLite,可通过版本化迁移脚本实现 schema 安全变更:
1. 初始化版本控制表
创建 schema_version 表记录当前数据库版本,确保每次启动都能识别需要执行的迁移:
CREATE TABLE IF NOT EXISTS schema_version ( version INTEGER PRIMARY KEY NOT NULL ); INSERT OR IGNORE INTO schema_version (version) VALUES (1);
2. 编写版本化迁移脚本
为每个 schema 变更编写独立脚本,确保脚本幂等(重复执行不会报错):
-- 迁移至版本 2:为 user 表添加 phone 字段 ALTER TABLE user ADD COLUMN phone TEXT; UPDATE schema_version SET version = 2;
-- 迁移至版本 3:创建 orders 表 CREATE TABLE IF NOT EXISTS orders ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER, amount REAL, FOREIGN KEY (user_id) REFERENCES user(id) ); UPDATE schema_version SET version = 3;
3. 应用启动时执行迁移
在应用初始化逻辑中,检查当前版本并执行未完成的迁移,用事务保证原子性:
import { CapacitorSQLite } from '@capacitor/sqlite'; async runMigrations() { const db = await CapacitorSQLite.createConnection({ database: 'app_local_db' }); await db.open(); // 获取当前版本 const versionRes = await db.query('SELECT version FROM schema_version'); let currentVersion = versionRes.values[0]?.version || 0; // 按版本顺序定义迁移脚本 const migrations = [ { version: 1, script: ` CREATE TABLE IF NOT EXISTS user (id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL); INSERT OR IGNORE INTO schema_version (version) VALUES (1); ` }, { version: 2, script: /* 版本2脚本 */ }, { version: 3, script: /* 版本3脚本 */ } ]; // 执行未完成的迁移 for (const migration of migrations) { if (migration.version > currentVersion) { try { await db.run(migration.script); currentVersion = migration.version; } catch (error) { console.error(`迁移至版本 ${migration.version} 失败:`, error); // 可添加回滚或报错提示逻辑 break; } } } await db.close(); }
关键注意事项
- 复杂变更(如拆分表、修改字段类型)需先备份数据,迁移完成后恢复,避免数据丢失。
- 所有迁移脚本需在测试环境验证通过后,再部署到生产环境。
内容的提问来源于stack exchange,提问作者The Sammie
相关产品推荐
相关产品推荐

