更新记录
0.5.1(2025-08-29)
文档修正
0.5.0(2025-08-29)
初始发布 v0.5.0
平台兼容性
云端兼容性
阿里云 | 腾讯云 | 支付宝云 |
---|---|---|
√ | √ | √ |
uni-app x(4.75)
Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
---|---|---|---|---|---|
× | × | 8.0 | × | 12 | × |
其他
多语言 | 暗黑模式 | 宽屏模式 |
---|---|---|
× | × | √ |
bsx-sqlite
关于
一款支持鸿蒙NEXT 5.0+ 和Aandroid 8+的sqlite操作API插件(uniapp x)
初衷
由于作者本人项目,需要建一个本地单词字典数据库,使用SQLITE操作。故开发该API 以支持Android和鸿蒙NEXT。现将,API作为插件提供给大家。 作者能力有限,不足之处,请包涵。
说明
- 支持android 8+ (api 26+)、HarmonyOS Next 5.0+ (api 12+)
- 暂未支持加密
- HarmonyOS next暂不支持子线程,android端可自行使用官方的派发线程api执行相关操作
- 均使用sqlite3 wal模式
- delete和update操作row时需注意指定操作的行(一般指定为条件为主键对应的记录),即谓词条件;避免更新或删除非预想的记录
- 注意! 数据脚本,包括表名\SQL语句等是不区分大小写的. 数据库文件是区分大小写的! (app.db 和APP.db 不一样)
- 备份和恢复数据时的文件,可自行管理文件版本,本API不涉及;备份或恢复切勿输入错误的数据文件名!默认备份文件统一添加了_backup字符结尾
- 默认数据库文件都是在应用沙盒目录的数据根目录(databases)下, 暂不支持自定义路径(需求量小). 如果需要持久保留,建议自行备份到云端
- 批次SQL(增、删、改)支持事务;Android 支持冲突模式.
- 暂未处理Uint8Array类型,即不支持二进制数据操作。暂请勿用
- 实例注意事项:使用完必需关闭数据库连接,避免资源溢出。每个bsxsqlite实例包含一个连接,也可以定义 一个全局操作对象。无论如何必需显示关闭连接!
类型
// 用于操作查询的参数类型
type SqlSelectParmType = number | string | boolean | null
// 用于操作数据的值类型
type ValueType = number | string | Uint8Array | boolean | null
type ValueContent = Map<string, ValueType>
type ConflictResolution = 'ON_CONFLICT_NONE' | 'ON_CONFLICT_ROLLBACK' | 'ON_CONFLICT_ABORT' | 'ON_CONFLICT_FAIL' | 'ON_CONFLICT_IGNORE' | 'ON_CONFLICT_REPLACE'
type TransationExecuteObj = {
sql: string
args: Array<ValueType> | null
}
class BsxSqlite {
...
}
使用
<template>
<view class="mx-3 flex-column">
<scroll-view scroll-y="true" class="border border-1 p-2" style="height: 150;">
<view v-for="user in userTable" class="flex-row justify-content-between align-content-center mb-1">
<text class="p-1">
id:{{ user.id }},{{user.name}},{{user.age}},{{user.enable}},{{user.address}}
</text>
<view class="p-1 flex-row">
<text class="me-4" @tap="execute('update', user.id)">update</text>
<text class="" @tap="execute('delete', user.id)">delete</text>
</view>
</view>
</scroll-view>
<view class="flex-row flex-wrap mt-3">
<button class="w-45 me-2 mb-2" @tap="execute('query')">查询</button>
<button class="w-45 me-2 mb-2" @tap="execute('createTB')">表创建</button>
<button class="w-45 me-2 mb-2" @tap="execute('deleteTB')">Delete表重置</button>
<button class="w-45 me-2 mb-2" @tap="execute('dropTB')">Drop表删除</button>
<button class="w-45 me-2 mb-2" @tap="execute('insert')">新增</button>
<button class="w-45 me-2 mb-2" @tap="execute('insertBatch')">批量新增</button>
<button class="w-45 me-2 mb-2" @tap="execute('transation')">事务执行SQL</button>
<button class="w-45 me-2 mb-2" @tap="open">打开连接</button>
<button class="w-45 me-2 mb-2" @tap="close">关闭连接</button>
<button class="w-45 me-2 mb-2" @tap="backup">备份数据库</button>
<button class="w-45 me-2 mb-2" @tap="restore">恢复数据库</button>
</view>
</view>
<scroll-view class="mx-5 mt-3 flex-column" style="height:220;">
<text v-for="item in message">
{{ item }}
</text>
</scroll-view>
</template>
<script setup>
import { BsxSqlite, SqlSelectParmType, ValueType, ValueContent, TransationExecuteObj } from '@/uni_modules/bsx-sqlite'
type user = {
id : number
name : string
age : number
enable : boolean | number
address : string | null
}
const dbDomain = ref<BsxSqlite | null>(null)
const message = ref<string[]>([])
const userTable = ref<user[]>([])
onReady(() => {
dbDomain.value = new BsxSqlite('app.db', 1)
dbDomain.value?.openDb().then(() => {
message.value.unshift('-- db is opened --')
})
})
const randomName = (len : number) : string => {
const strs = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
let result = '';
for (let i = 0; i < len; i++) {
result += strs.charAt(Math.floor(Math.random() * strs.length))
}
return result;
}
const refresh = async () => {
const ret : UTSJSONObject = await dbDomain.value?.query("SELECT * FROM Users")!
console.log('--- userTable.value ---', ret)
try {
const dataStr = JSON.stringify(ret!['data'])
userTable.value = JSON.parseArray<user>(dataStr!)!
} catch (err) {
console.log('--- 刷新数据异常 -----', err)
}
}
async function execute(key : string, _id : number = -1) {
let ret = {} as UTSJSONObject
if (key == 'createTB') {
ret = await dbDomain.value?.createTable("CREATE TABLE IF NOT EXISTS Users (id INTEGER PRIMARY KEY, name TEXT not null, age INTEGER DEFAULT 0 not null, enable BOOLEAN DEFAULT false, address TEXT DEFAULT null)")!
}
if (key == 'dropTB') {
ret = await dbDomain.value?.executeSql("DROP TABLE Users")!
}
if (key == 'insert') {
let insertData : Map<string, ValueType> = new Map();
const newName : ValueType = randomName(6) as string
insertData.set('name', newName)
insertData.set('age', 123)
ret = await dbDomain.value?.insert("Users", insertData as ValueContent)!
}
if (key == 'insertBatch') {
let insertData1 : Map<string, ValueType> = new Map();
let insertData2 : Map<string, ValueType> = new Map();
const newName1 : ValueType = randomName(6) as string
const newName2 : ValueType = randomName(6) as string
insertData1.set('name', newName1)
insertData1.set('age', 456)
insertData2.set('name', newName2)
let ary : Array<ValueContent> = []
ary.push(insertData1, insertData2)
ret = await dbDomain.value?.insertBatchRows("Users", ary)!
}
if (key == 'update') {
let updateData : Map<string, ValueType> = new Map()
updateData.set('age', 666)
ret = await dbDomain.value?.update("Users", "id", _id, updateData as ValueContent)!
}
if (key == 'delete') {
ret = await dbDomain.value?.delete("Users", "id", _id)!
}
if (key == 'query') {
ret = await dbDomain.value?.query("SELECT * FROM Users")!
}
if (key == 'deleteTB') {
ret = await dbDomain.value?.executeSqlWithTransation([
{
sql: 'delete from users',
args: null
},
{
sql: "delete from sqlite_sequence where name = 'users'",
args: null
}
] as Array<TransationExecuteObj>)!
}
if (key == 'transation') {
// 注意!这里必需使用Any[]类型 预制事务脚本.以便兼容android和harmonyOS next
let ary:Any[] = []
for (let i = 0; i < 10; i++) {
const newName : ValueType = randomName(6) as string
// 模拟更新
if (i == 5) {
ary.push({
sql: "update users set name = ?, age =? where id = ?",
args: [newName, 777, i - 2]
})
} else {
ary.push({
sql: "insert into users (name, age) values (?, ?)",
args: [newName, 999]
})
}
}
// 兼容android 必需类型转换
ret = await dbDomain.value?.executeSqlWithTransation(JSON.parseArray<TransationExecuteObj>(JSON.stringify(ary)!)!)!
}
message.value.unshift(JSON.stringify(ret))
await refresh()
}
const open = async () => {
if (dbDomain.value == null || !dbDomain.value.isConnected()) {
dbDomain.value = new BsxSqlite('app.db', 1)
await dbDomain.value?.openDb()
message.value.unshift('-- db is opened --')
}
}
const close = () => {
dbDomain.value?.closeDb().then((ret : UTSJSONObject) => {
if (ret.getString('status') == 'success') {
dbDomain.value = null
}
message.value.unshift('-- db is closed --')
})
}
const backup = () => {
// 实际的备份文件是 backupDb_backup.db
dbDomain.value?.backup("backupDb.db").then((ret : UTSJSONObject) => {
message.value.unshift(JSON.stringify(ret))
})
}
const restore = () => {
// 实际的恢复文件是 backupDb_backup.db
dbDomain.value?.restore("backupDb.db").then((ret : UTSJSONObject) => {
message.value.unshift(JSON.stringify(ret))
})
}
onUnload(() => {
dbDomain.value?.closeDb().then((res) => {
console.log('--- onUnload -----', res)
})
})
</script>
<style>
</style>