数据库
介绍
数据库模块提供本地持久化能力,当前以 Demo 作为最小示例,演示实体定义、数据源接口与数据源实现。实际业务可按此结构扩展。
设计思路
- 数据库模块只负责数据的本地读写,不直接给业务层使用。
- 上层通过
DemoRepository等仓库访问数据,保证数据入口统一。 - 详细数据库使用请参考官方文档: https://ibest-orm.ibestservices.com/
实体示例
文件位置:core/database/src/main/ets/entity/DemoEntity.ets
ts
import { Column, ColumnType, CreatedAt, PrimaryKey, Table, UpdatedAt } from "@ibestservices/ibest-orm";
/**
* @file Demo 表实体定义
*/
@Table({ name: "demo_items" })
export class DemoEntity {
/**
* 主键 ID
*/
@PrimaryKey({ autoIncrement: true })
id?: number;
/**
* 标题
*/
@Column({ type: ColumnType.TEXT })
title?: string;
/**
* 描述
*/
@Column({ type: ColumnType.TEXT })
description?: string;
/**
* 创建时间
*/
@CreatedAt()
createdAt?: string;
/**
* 更新时间
*/
@UpdatedAt()
updatedAt?: string;
}数据源接口示例
文件位置:core/database/src/main/ets/datasource/demo/DemoLocalDataSource.ets
ts
import { DemoEntity } from "../../entity/DemoEntity";
/**
* @file Demo 数据源接口,定义本地 CRUD 能力
*/
export interface DemoLocalDataSource {
/**
* 新增一条 Demo 记录
* @param {string} title - 标题
* @param {string} [description] - 描述
* @returns {Promise<number>} 新建记录主键
*/
createItem(title: string, description?: string): Promise<number>;
/**
* 更新 Demo 记录
* @param {DemoEntity} entity - 待更新实体
* @returns {Promise<void>} Promise<void>
*/
updateItem(entity: DemoEntity): Promise<void>;
/**
* 按主键删除 Demo 记录
* @param {number} id - 记录主键
* @returns {Promise<void>} Promise<void>
*/
deleteById(id: number): Promise<void>;
/**
* 清空 Demo 表
* @returns {Promise<number>} 受影响行数
*/
clearAll(): Promise<number>;
/**
* 查询全部 Demo 记录,默认按更新时间倒序
* @returns {Promise<DemoEntity[]>} Demo 列表
*/
getAllItems(): Promise<DemoEntity[]>;
/**
* 根据主键查询单条记录
* @param {number} id - 记录主键
* @returns {Promise<DemoEntity | undefined>} 匹配到的 Demo 或 undefined
*/
getItemById(id: number): Promise<DemoEntity | undefined>;
}数据源实现示例
文件位置:core/database/src/main/ets/datasource/demo/DemoLocalDataSourceImpl.ets
ts
import { getORM } from "@ibestservices/ibest-orm";
import { DemoEntity } from "../../entity/DemoEntity";
import { DemoLocalDataSource } from "./DemoLocalDataSource";
/**
* @file Demo 数据源实现,基于 IBest-ORM 封装 CRUD
*/
export class DemoLocalDataSourceImpl implements DemoLocalDataSource {
/**
* 迁移标记,避免重复建表
*/
private static migrated: boolean = false;
/**
* ORM 实例
*/
private orm = getORM();
constructor() {
this.ensureMigrated();
}
/**
* 确保 Demo 表完成迁移
* @returns {void} 无返回
*/
private ensureMigrated(): void {
if (!DemoLocalDataSourceImpl.migrated) {
this.orm.migrate(DemoEntity);
DemoLocalDataSourceImpl.migrated = true;
}
}
/**
* 新增一条 Demo 记录
* @param {string} title - 标题
* @param {string} description - 描述
* @returns {Promise<number>} 新建记录主键
*/
async createItem(title: string, description: string = ""): Promise<number> {
const entity: DemoEntity = new DemoEntity();
entity.title = title;
entity.description = description;
return this.orm.insert(entity);
}
/**
* 更新 Demo 记录
* @param {DemoEntity} entity - 待更新实体
* @returns {Promise<void>} Promise<void>
*/
async updateItem(entity: DemoEntity): Promise<void> {
this.orm.save(entity);
}
/**
* 按主键删除 Demo 记录
* @param {number} id - 记录主键
* @returns {Promise<void>} Promise<void>
*/
async deleteById(id: number): Promise<void> {
this.orm.deleteById(DemoEntity, id);
}
/**
* 清空 Demo 表
* @returns {Promise<number>} 受影响行数
*/
async clearAll(): Promise<number> {
return this.orm.query(DemoEntity).delete();
}
/**
* 查询全部 Demo 记录并按更新时间倒序
* @returns {Promise<DemoEntity[]>} Demo 列表
*/
async getAllItems(): Promise<DemoEntity[]> {
const list: DemoEntity[] = this.orm.query(DemoEntity).find();
// 以更新时间/创建时间倒序排列,便于展示最新数据
return list.sort((left: DemoEntity, right: DemoEntity) => {
const leftTime: number = new Date(left.updatedAt ?? left.createdAt ?? "").getTime() || 0;
const rightTime: number = new Date(right.updatedAt ?? right.createdAt ?? "").getTime() || 0;
return rightTime - leftTime;
});
}
/**
* 根据主键查询单条记录
* @param {number} id - 记录主键
* @returns {Promise<DemoEntity | undefined>} 匹配到的 Demo 或 undefined
*/
async getItemById(id: number): Promise<DemoEntity | undefined> {
const result: DemoEntity[] = this.orm.query(DemoEntity).where("id", id).find();
return result[0];
}
}仓库实现示例
文件位置:core/data/src/main/ets/repository/DemoRepository.ets
ts
import { DemoEntity, DemoLocalDataSource, DemoLocalDataSourceImpl } from "database";
/**
* @file Demo 仓库,衔接业务层与本地数据库
*/
export class DemoRepository {
/**
* Demo 本地数据源
*/
private demoLocalDataSource: DemoLocalDataSource;
/**
* 构造函数
* @param {DemoLocalDataSource} [localDataSource] - 可选的本地数据源
*/
constructor(localDataSource?: DemoLocalDataSource) {
this.demoLocalDataSource = localDataSource ?? new DemoLocalDataSourceImpl();
}
/**
* 创建 Demo 记录
* @param {string} title - 标题
* @param {string} description - 描述
* @returns {Promise<number>} 新建记录主键
*/
async createDemo(title: string, description: string = ""): Promise<number> {
return this.demoLocalDataSource.createItem(title, description);
}
/**
* 更新 Demo 记录
* @param {DemoEntity} entity - 待更新实体
* @returns {Promise<void>} Promise<void>
*/
async updateDemo(entity: DemoEntity): Promise<void> {
return this.demoLocalDataSource.updateItem(entity);
}
/**
* 删除指定 ID 的 Demo 记录
* @param {number} id - 记录主键
* @returns {Promise<void>} Promise<void>
*/
async deleteDemo(id: number): Promise<void> {
return this.demoLocalDataSource.deleteById(id);
}
/**
* 清空全部 Demo 记录
* @returns {Promise<number>} 受影响行数
*/
async clearAll(): Promise<number> {
return this.demoLocalDataSource.clearAll();
}
/**
* 获取所有 Demo 记录
* @returns {Promise<DemoEntity[]>} Demo 列表
*/
async getAll(): Promise<DemoEntity[]> {
return this.demoLocalDataSource.getAllItems();
}
/**
* 根据主键查询单条 Demo 记录
* @param {number} id - 记录主键
* @returns {Promise<DemoEntity | undefined>} 匹配到的 Demo 或 undefined
*/
async getById(id: number): Promise<DemoEntity | undefined> {
return this.demoLocalDataSource.getItemById(id);
}
}ViewModel 使用示例
文件位置:feature/demo/src/main/ets/viewmodel/DatabaseViewModel.ets
下面截取两段常用逻辑,展示如何通过仓库访问数据库。
ts
import { BaseViewModel } from "base";
import { DemoEntity, DemoRepository } from "data";
/**
* @file 数据库示例页 ViewModel
*/
@ObservedV2
export default class DatabaseViewModel extends BaseViewModel {
/**
* Demo 仓库
*/
private demoRepository: DemoRepository = new DemoRepository();
/**
* 保存记录(新增或更新)
* @returns {Promise<void>} Promise<void>
*/
async save(): Promise<void> {
await this.runWithLoading(async (): Promise<void> => {
if (this.editingId > 0) {
await this.updateById(this.editingId);
} else {
await this.demoRepository.createDemo(this.titleInput, this.descInput);
}
this.resetInputs();
await this.fetchList();
});
}
/**
* 删除指定记录
* @param {number} id - 记录主键
* @returns {Promise<void>} Promise<void>
*/
async delete(id: number): Promise<void> {
if (!id) {
return;
}
await this.runWithLoading(async (): Promise<void> => {
await this.demoRepository.deleteDemo(id);
if (this.editingId === id) {
this.resetInputs();
}
await this.fetchList();
});
}
/**
* 更新指定 ID 的记录
* @param {number} id - 记录主键
* @returns {Promise<void>} Promise<void>
*/
private async updateById(id: number): Promise<void> {
const entity: DemoEntity = new DemoEntity();
entity.id = id;
entity.title = this.titleInput.trim();
entity.description = this.descInput.trim();
await this.demoRepository.updateDemo(entity);
}
}与数据层的关系
- 数据库模块不直接给业务层使用。
- 业务通过
DemoRepository访问数据库数据。 - Repository 统一对外提供业务语义方法,保持依赖收敛。
新增表的做法
如果要新增表,建议按 Demo 的结构来做:
- 在
core/database/src/main/ets/datasource/下新增一个与表名一致的文件夹。 - 在该文件夹内编写数据源接口与实现(参考 Demo 的接口与实现)。
- 在
entity/下新增对应实体类。 - 在
core/database/Index.ets中补充导出,保证外部可以统一引入。 - 在 data 层新增对应 Repository,对外提供业务语义方法。
注意事项
- Demo 只是示例,真实业务请按需要扩展实体与数据源。
- 数据库能力与完整使用方法请参考 IBest-ORM 官方文档。