更新记录

2.3.5(2025-01-19) 下载此版本

新增事务管理代码

2.3.3(2025-01-19) 下载此版本

推送实例代码

2.3.2(2025-01-19) 下载此版本

更改项目结构

查看更多

平台兼容性

Vue2 Vue3
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
HBuilderX 3.8.12 app-vue × × × × × ×
钉钉小程序 快手小程序 飞书小程序 京东小程序 鸿蒙元服务
× × × × ×
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
× × × × × × × × ×

uniapp操作sqlite数据库

uniapp插件地址

uniapp操作sqlite数据库的orm框架,完全使用TS编写。该框架模仿mybatisplus风格,使用简单,业务层无需关心数据库操作,只需要调用相应的API即可。数据库查询操作,考虑到API封装的复杂度,暂时采用sql原生脚本拼接。

sqlite数据库是需要使用sql脚本创建相应的数据表,但是当前组件中已经编写好自动创建表的代码,只需编写好实体,在实体上指定好注解,在 @/uni_modules/stars-UniTS-SQLite-ORM/components/dbOrm/db/TableInit文件中指定实体即可,下面详细介绍。

在使用该组件时,推荐先下载实例看看。实例代码并没有封装在组件中。

一、使用案例

<template>
    <view class="content">
        <button @click="addUser">添加用户数据</button>
        <button @click="selectUser">查询数据</button>
    </view>
</template>

<script lang="ts">
    import { User } from '@/pages/example/model/User';
    import { UserServiceImpl } from '@/pages/example/service/UserServiceImpl';
    const userService = new UserServiceImpl();
    export default {
        data() {
            return {
                title: 'Hello'
            }
        },
        onLoad() {
            // this.addUser()
        },
        methods: {
            // 添加数据
            async addUser() {
                try {
                    // 插入数据
                    const user = new User();
                    user.name = '张三';
                    user.age = Math.floor(Math.random() * (35 - 18 + 1)) + 18;
                    user.price = 235
                    await userService.insertUser(user);

                    console.log("数据添加成功");

                    // 根据主键查询数据
                    const userById = await userService.getUserById(1);
                    console.log('根据主键查询数据:', userById);

                    // 查询所有数据
                    const userList = await userService.getUsers();
                    console.log('查询所有数据:', userList);

                    // 根据条件查询数据
                    const userByCondition = await userService.getUsersByCondition("age > 18");
                    console.log('根据条件查询数据:', userByCondition);

                    // 分页查询数据
                    const page = 3;
                    const size = 10;
                    const userPage = await userService.getUsersByPage(page, size, "age > 18", "age ASC");
                    console.log('分页查询数据:', userPage);
                    console.log(userById);
                    // 更新数据
                    userById.name = '李四';
                    await userService.updateUser(userById);

                    // 根据主键删除数据
                    // await userService.deleteUserById(3);

                    // 根据条件删除数据
                    // await userService.deleteUserByCondition("age < 30");
                } catch (error) {
                    console.error('An error occurred during database operation:', error);
                }
            },

            // 查询数据
            async selectUser() {
                try {
                    const user = await userService.getUsersByCondition("age > 30 and (id <=5 and id >= 2)")
                    console.log(user);
                } catch (error) {
                    console.error('An error occurred during database operation:', error);
                }
            }
        }
    }
</script>

<style>
    .content {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }
</style>

二、数据实体封装

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()注解修饰的表示数据库的主键,只要是修饰主键的字段类型必须为 INTEGERl类型,数据库的主键列默认是自增的,所以插入数据时就无需再给主键赋值。

  • @NotNull()

非空,@NotNull()注解修饰的字段,添加数据时必须有数据,不能为空。

  • @FieldType

注解中有三个属性,field指定数据库中的字段,type字段类型,length字段长度【可选】

例如:@FieldType({ field: 'name', type: FieldTypeEnum.TEXT, length: 255 })

三、业务实现

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<BaseModel>;

    constructor() {
        this.sqliteService = new SqliteServiceImpl<BaseModel>();
    }

    // 插入用户
    async insertUser(user : User) : Promise<void> {
        return await this.sqliteService.insert(user);
    }

    // 根据 ID 获取用户
    async getUserById(id : number) : Promise<User> {
        return await this.sqliteService.selectById(id, User);
    }

    // 获取所有用户
    async getUsers() : Promise<User[]> {
        return await this.sqliteService.selectAll(User);
    }

    // 根据条件获取用户
    async getUsersByCondition(condition : string) : Promise<User[]> {
        return await this.sqliteService.selectByCondition(condition, User);
    }

    /**
     * 分页查询用户
     */
    async getUsersByPage(page : number, size : number, condition ?: string, orderBy ?: string) : Promise<PageModel> {
        return await this.sqliteService.selectByPage(page, size, condition, orderBy, User);
    }

    // 更新用户
    async updateUser(user : User) : Promise<void> {
        return await this.sqliteService.update(user);
    }

    // 根据 ID 删除用户
    async deleteUserById(id : number) : Promise<void> {
        return await this.sqliteService.deleteById(id, User);
    }

    // 根据条件删除用户
    async deleteUserByCondition(condition : string) : Promise<void> {
        return await this.sqliteService.deleteByCondition(condition, User);
    }
}

考虑到前端操作数据库并不复杂,所以没有将数据操作层与业务完全拆封开。

四、配置说明

@/uni_modules/stars-sqlite-orm/components/stars-sqlite-orm/dbOrm/config/dbconfig文件中编写了数据库的配置信息。

// 数据库信息配置
// 数据库名称
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事件处理。处理的业务主要是对数据库的打开和关闭操作。当应用启动时,会自动打开数据库。当应用关闭时,会关闭数据库后再关闭应用。注意:应用是彻底关闭时才会关闭数据库,当应用隐藏到后台时,不会关闭数据库。特别注意:当应用并没有点击退出按钮,而是直接杀死应用进程,或者应用隐藏到后台,自动杀死进程的方式,数据库是不会关闭的。

<template>
    <div>
        <!-- 这里可以添加你的页面内容 -->
    </div>
</template>

<script lang="ts">
    import { appOpen } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/app/application.ts';

    export default {
        data() {
            return {
            };
        },
        created() {
            // 应用打开和关闭事件
            appOpen()
        },
        onLaunch() {
            console.log("应用创建");
        },
        onHide() {
            console.log("应用正在隐藏");
        },
        onShow() {
            console.log("应用正在显示");
        },
        methods: {
        }
    };
</script>

六、自动创建表

@/uni_modules/stars-UniTS-SQLite-ORM/components/dbOrm/db/TableInit文件中配置实体,应用启动时会自动判断数据表是否存在,如果数据表不存在则自动创建。

/**
 * 初始化表
 */
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文件配置

{
    "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 或调整为其他目标版本,如 es5es6
    • "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/*"] }:自定义模块路径映射,方便导入模块,根据项目结构和个人喜好可调整或保留。

关于 includeexclude

  • "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 模式、moduleResolutionesModuleInterop 等通常建议保留,以保证代码质量和模块的正常导入。

注意事项

  • 在修改 tsconfig.json 时,确保重新编译项目,以便新的配置生效。
  • 不同的配置项可能会影响项目的构建和运行,因此在调整时需要谨慎,特别是在修改 targetmodule 等关键选项时。

以下是一个简化但保留关键部分的 tsconfig.json 示例。

八、事务使用

直接在业务上使用 @Transactional注解即可.

  • 范例
// 事务测试
@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("处理业务逻辑结束");
}

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问