# 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("处理业务逻辑结束");
}
```