# uniapp-sqlite **Repository Path**: dungang/uniapp-sqlite ## Basic Information - **Project Name**: uniapp-sqlite - **Description**: uniapp操作sqlite数据库的orm框架,模仿mybatisplus风格。使用TS封装,支持VUE3,是否支撑uniappx暂时不知道,没有测试过。按道理来说是完全支持的,没有引入任何第三方工具,框架超级轻量级。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 3 - **Created**: 2025-02-28 - **Last Updated**: 2025-02-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # uniapp操作sqlite数据库 [uniapp插件地址](https://ext.dcloud.net.cn/plugin?id=21923) `uniapp`操作`sqlite`数据库的`orm`框架,完全使用`TS`编写。该框架模仿`mybatisplus`风格,使用简单,业务层无需关心数据库操作,只需要调用相应的`API`即可。数据库查询操作,考虑到`API`封装的复杂度,暂时采用`sql`原生脚本拼接。 `sqlite`数据库是需要使用`sql`脚本创建相应的数据表,但是当前组件中已经编写好自动创建表的代码,只需编写好实体,在实体上指定好注解,在 `@/uni_modules/stars-UniTS-SQLite-ORM/components/dbOrm/db/TableInit`文件中指定实体即可,下面详细介绍。 在使用该组件时,推荐先下载实例看看。实例代码并没有封装在组件中。 # 一、使用案例 ```vue ``` # 二、数据实体封装 ```ts import { BaseModel } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/model/BaseModel'; import { PrimaryKey, NotNull, FieldType } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/annotation/Decorators'; import { FieldTypeEnum } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/enum/FieldTypeEnum'; /** * 这个类的部分字段不符合user表,例如:用户是没有price字段,但是这个表是为了测试字段和注解等功能。 */ export class User extends BaseModel { @PrimaryKey() @NotNull() @FieldType({ field: 'id', type: FieldTypeEnum.INTEGER }) id : number; @FieldType({ field: 'name', type: FieldTypeEnum.TEXT, length: 255 }) @NotNull() name : string; @FieldType({ field: 'age', type: FieldTypeEnum.INTEGER }) age : number; @FieldType({ field: 'price', type: FieldTypeEnum.INTEGER }) price : number; @FieldType({ field: 'description', type: FieldTypeEnum.TEXT, length: 255 }) description : string; @FieldType({ field: 'createdDate', type: FieldTypeEnum.TEXT, length: 255 }) createdDate : Date; } ``` ## 注解详解 - `@PrimaryKey()` `@PrimaryKey()`注解修饰的表示数据库的主键,只要是修饰主键的字段类型必须为 `INTEGER`l类型,数据库的主键列默认是自增的,所以插入数据时就无需再给主键赋值。 - `@NotNull()` 非空,`@NotNull()`注解修饰的字段,添加数据时必须有数据,不能为空。 - `@FieldType` 注解中有三个属性,`field`指定数据库中的字段,`type`字段类型,`length`字段长度【可选】 例如:`@FieldType({ field: 'name', type: FieldTypeEnum.TEXT, length: 255 })` # 三、业务实现 ```tsx import { BaseModel } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/model/BaseModel'; import { PageModel } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/model/PageModel'; import { ISqliteService } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/service/ISqliteService'; import { SqliteServiceImpl } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/service/impl/SqliteServiceImpl'; import { User } from '../model/User'; export class UserServiceImpl { // 创建实现类的实例 private sqliteService : ISqliteService; constructor() { this.sqliteService = new SqliteServiceImpl(); } // 插入用户 async insertUser(user : User) : Promise { return await this.sqliteService.insert(user); } // 根据 ID 获取用户 async getUserById(id : number) : Promise { return await this.sqliteService.selectById(id, User); } // 获取所有用户 async getUsers() : Promise { return await this.sqliteService.selectAll(User); } // 根据条件获取用户 async getUsersByCondition(condition : string) : Promise { return await this.sqliteService.selectByCondition(condition, User); } /** * 分页查询用户 */ async getUsersByPage(page : number, size : number, condition ?: string, orderBy ?: string) : Promise { return await this.sqliteService.selectByPage(page, size, condition, orderBy, User); } // 更新用户 async updateUser(user : User) : Promise { return await this.sqliteService.update(user); } // 根据 ID 删除用户 async deleteUserById(id : number) : Promise { return await this.sqliteService.deleteById(id, User); } // 根据条件删除用户 async deleteUserByCondition(condition : string) : Promise { return await this.sqliteService.deleteByCondition(condition, User); } } ``` 考虑到前端操作数据库并不复杂,所以没有将数据操作层与业务完全拆封开。 # 四、配置说明 在 `@/uni_modules/stars-sqlite-orm/components/stars-sqlite-orm/dbOrm/config/dbconfig`文件中编写了数据库的配置信息。 ```tsx // 数据库信息配置 // 数据库名称 export const DB_NAME : string = 'user_db'; // 数据库的数据保存地址,如果这里配置了,那么就以这里的为准,否则以系统自动分配 export const DB_PATH : string = ''; // 关闭应用处理时间,单位:毫秒。就是用户关闭应用后,需要留多长时间来给业务处理,比如:200秒,那么用户点击关闭应用后,会留200秒来处理业务,200秒后,应用才会真正的关闭 export const DB_CLOSE_TIMEOUT : number = 200; ``` 可能会更改的就是数据库名称 `DB_NAME`。 # 五、App.vue文件配置 在`App.vue`文件中需要指定 `created`事件处理。处理的业务主要是对数据库的打开和关闭操作。当应用启动时,会自动打开数据库。当应用关闭时,会关闭数据库后再关闭应用。注意:应用是彻底关闭时才会关闭数据库,当应用隐藏到后台时,不会关闭数据库。特别注意:当应用并没有点击退出按钮,而是直接杀死应用进程,或者应用隐藏到后台,自动杀死进程的方式,数据库是不会关闭的。 ```vue ``` # 六、自动创建表 在 `@/uni_modules/stars-UniTS-SQLite-ORM/components/dbOrm/db/TableInit`文件中配置实体,应用启动时会自动判断数据表是否存在,如果数据表不存在则自动创建。 ```js /** * 初始化表 */ public static tableInit() : void { const createProductTableSQL = CrateTable.generateCreateTableSQL(User); console.log(createProductTableSQL); executeSql(DB_NAME, createProductTableSQL); executeSql(DB_NAME, CrateTable.generateCreateTableSQL(实体名即可)); console.log("创建表成功:", User.name.toLowerCase()); } ``` # 七、`tsconfig.json`文件配置 ```json { "compilerOptions": { "target": "esnext", "module": "esnext", "strict": true, "moduleResolution": "node", "esModuleInterop": true, "allowSyntheticDefaultImports": true, "experimentalDecorators": true, "emitDecoratorMetadata": true }, "include": [ "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue" ], "exclude": [ "node_modules", "unpackage", "dist" ] } ``` - `"compilerOptions": {... }` :包含了 TypeScript 编译器的各种选项,是整个配置的核心部分。 - `"target": "esnext"`:指定编译后的 JavaScript 代码的目标版本。根据你的项目需求,可以保持为 `esnext` 或调整为其他目标版本,如 `es5` 或 `es6`。 - `"module": "esnext"`:指定模块系统,`esnext` 表示使用最新的模块系统,可根据实际情况调整。 - `"strict": true`:启用严格模式,这有助于发现更多潜在的错误,建议保持为 `true`。 - `"moduleResolution": "node"`:使用 Node.js 的模块解析策略,对于大多数项目是适用的。 - `"esModuleInterop": true`:允许在 CommonJS 和 ES 模块之间进行互操作,在使用第三方模块时可能会用到,建议保留。 - `"allowSyntheticDefaultImports": true`:允许从没有默认导出的模块中导入默认导出,在使用一些库时可能会需要,建议保留。 - `"sourceMap": true`:生成源映射文件,方便调试,在开发阶段比较有用,可根据情况决定是否保留。 - `"experimentalDecorators": true`:因为你使用了装饰器(如 `@Transactional`),此选项必须设置为 `true`,以便编译器识别和处理装饰器。 - `"emitDecoratorMetadata": true`:如果你使用的装饰器需要元数据,这个选项也应该设置为 `true`,对于使用装饰器的项目很重要,建议保留。 **可根据项目调整的配置项**: - `"baseUrl": "."`:指定基本目录,可根据项目结构调整。 - `"types": ["uniapp"]`:指定引入的类型声明文件,如果你使用了 UniApp 相关的类型声明,可以保留。 - `"paths": { "@/*": ["./src/*"] }`:自定义模块路径映射,方便导入模块,根据项目结构和个人喜好可调整或保留。 **关于 `include` 和 `exclude`**: - `"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "typings/**/*.d.ts", "types/**/*.d.ts"]`:指定需要编译的文件,可根据项目文件的位置和扩展名进行调整。确保包含了你的 `*.ts` 文件,尤其是使用装饰器的文件。 - `"exclude": ["node_modules", "unpackage", "dist"]`:排除不需要编译的目录,可根据项目结构进行调整,一般不需要修改。 **总结**: - 对于使用装饰器的项目,`"experimentalDecorators": true` 和 `"emitDecoratorMetadata": true` 是不可或缺的,以确保 TypeScript 编译器能正确处理装饰器。 - 其他配置项可根据项目的具体需求和结构进行调整,但 `strict` 模式、`moduleResolution` 和 `esModuleInterop` 等通常建议保留,以保证代码质量和模块的正常导入。 **注意事项**: - 在修改 `tsconfig.json` 时,确保重新编译项目,以便新的配置生效。 - 不同的配置项可能会影响项目的构建和运行,因此在调整时需要谨慎,特别是在修改 `target` 和 `module` 等关键选项时。 以下是一个简化但保留关键部分的 `tsconfig.json` 示例。 # 八、事务使用 直接在业务上使用 `@Transactional`注解即可. - 范例 ```tsx // 事务测试 @Transactional transactionalTest(user : User) : void { console.log("处理业务逻辑开始"); this.sqliteService.insert(user); let users = new User(); users.id = 1; users.name = '这是更改后的名字'; this.sqliteService.update(users); this.sqliteService.deleteById(2, User); // 制造一个异常 this.sqliteService.update(null); throw new Error("制造一个异常"); console.log("处理业务逻辑结束"); } ```