@react-native-ohos/op-sqlite
v15.0.0
Published
Fastest SQLite for React Native (with node.js support)
Readme
文档模板:v0.4.1
@op-engineering/op-sqlite
本项目基于@op-engineering/op-sqlite 开发
该第三方库的仓库已迁移至 Gitcode,且支持直接从 npm 下载,新的包名为:@react-native-ohos/op-sqlite 版本所属关系如下:
| 三方库名称 | 三方库版本 | 发布信息 | 支持RN版本 | Autolink | 编译API版本 | 社区基线版本 | npm地址 | | - | - | - | - | - | - | - | - | | @react-native-ohos/op-sqlite | ~ 15.0.0 | Gitcode Releases | 0.82.* | 是 | API12+ | 16.2.0 | Npm Address | | @react-native-ohos/op-sqlite | ~ 14.0.1 | Gitcode Releases | 0.77.* | 否 | API12+ | 14.0.0 | Npm Address | | @react-native-ohos/op-sqlite | ~ 8.0.3 | Gitcode Releases | 0.72.* | 是 | API12+ | 8.0.2 | Npm Address | | @react-native-oh-tpl/op-sqlite | <= 8.0.2-0.0.3@deprecated | Github Releases(deprecated) | 0.72.* | 否 | API12+ | 8.0.2 | Npm Address |
简介
op-sqlite 是一个用于 React Native 应用程序的高性能 SQLite 数据库库。它提供了同步/异步执行 SQL、事务、预编译语句、批量执行、响应式查询以及远程数据库同步等能力,并可选择性地启用 SQLCipher 加密或 libsql 远程模式。
下载安装
进入到工程目录并输入以下命令:
npm
npm install @react-native-ohos/op-sqliteyarn
yarn add @react-native-ohos/op-sqliteLink
| | 是否支持autolink | RN框架版本 | | - | - | - | | ~15.0.0 | 是 | 0.82 |
使用AutoLink的工程需要根据该文档配置,Autolink框架指导文档:https://gitcode.com/CPF-RN/ohos_react_native/blob/master/docs/zh-cn/Autolinking.md
如您使用的版本支持 Autolink,并且工程已接入 Autolink,可跳过ManualLink配置。
首先需要使用 DevEco Studio 打开项目里的 HarmonyOS 工程 harmony。
1. Overrides RN SDK
为了让工程依赖同一个版本的 RN SDK,需要在工程根目录的 oh-package.json5 添加 overrides 字段,指向工程需要使用的 RN SDK 版本。替换的版本既可以是一个具体的版本号,也可以是一个模糊版本,还可以是本地存在的 HAR 包或源码目录。
关于该字段的作用请阅读官方说明
{
"overrides": {
"@rnoh/react-native-openharmony": "^0.82.30" // ohpm 在线版本
// "@rnoh/react-native-openharmony" : "./react_native_openharmony.har" // 指向本地 har 包的路径
// "@rnoh/react-native-openharmony" : "./react_native_openharmony" // 指向源码路径
}
}2. 引入原生端代码
目前有两种方法:
- 通过 har 包引入(在 IDE 完善相关功能后该方法会被遗弃,目前首选此方法);
- 直接链接源码。
方法一:通过 har 包引入(推荐)
[!TIP] har 包位于三方库安装路径的
harmony文件夹下。
打开 entry/oh-package.json5,添加以下依赖
"dependencies": {
"@rnoh/react-native-openharmony": "file:../react_native_openharmony",
"@react-native-ohos/op-sqlite": "file:../../node_modules/@react-native-ohos/op-sqlite/harmony/rn_op_sqlite.har"
}点击右上角的 sync 按钮
或者在终端执行:
cd entry
ohpm install方法二:直接链接源码
[!TIP] 如需使用直接链接源码,请参考直接链接源码说明
3. 配置 CMakeLists 和引入 RNOpSqlitePackage
打开 entry/src/main/cpp/CMakeLists.txt,添加:
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+ set(NODE_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../node_modules")
+ set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../react-native-harmony/harmony/cpp")
set(LOG_VERBOSITY_LEVEL 1)
set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use
add_compile_definitions(WITH_HITRACE_SYSTRACE)
add_subdirectory("${RNOH_CPP_DIR}" ./rn)
# RNOH_BEGIN: manual_package_linking_1
add_subdirectory("../../../../sample_package/src/main/cpp" ./sample-package)
+ add_subdirectory("${OH_MODULES}/@react-native-ohos/op-sqlite/src/main/cpp" ./rn_op_sqlite)
# RNOH_END: manual_package_linking_1
file(GLOB GENERATED_CPP_FILES "./generated/*.cpp")
add_library(rnoh_app SHARED
${GENERATED_CPP_FILES}
"./PackageProvider.cpp"
"${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
target_link_libraries(rnoh_app PUBLIC rnoh)
# RNOH_BEGIN: manual_package_linking_2
target_link_libraries(rnoh_app PUBLIC rnoh_sample_package)
+ target_link_libraries(rnoh_app PUBLIC rnoh_rn_op_sqlite)
# RNOH_END: manual_package_linking_2[!Tip] 注意:上面 NODE_MODULES 定义为源库的安装路径,用户可以根据安装源库的路径定义 NODE_MODULES。
打开 entry/src/main/cpp/PackageProvider.cpp,添加:
#include "RNOH/PackageProvider.h"
#include "SamplePackage.h"
+ #include "RNOpSqlitePackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<SamplePackage>(ctx),
+ std::make_shared<RNOpSqlitePackage>(ctx)
};
}4. 在 ArkTs 侧引入 RNOpSqlitePackage
打开 entry/src/main/ets/RNPackagesFactory.ts,或者 entry/src/main/ets/rn/RNPackagesFactory.ts,添加:
...
+ import { RNOpSqlitePackage } from '@react-native-ohos/op-sqlite/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
new SamplePackage(ctx),
+ new RNOpSqlitePackage(ctx),
];
}5. 必要的配置项
[!TIP] 该模块的内容无法通过 autolink 自动生成,始终需要手动配置。
(1) 在 ide 的工程根目录创建 package.json 文件,并配置参数(该模块始终需要手动配置)
{
...
"op-sqlite": {
...
"sqlcipher": false,
"libsql": false, //此处设置为 true 即为远程数据库模式
...
},
...
}(2) 在 ArkTs 侧引入 opSqlitePlugin(该模块始终需要手动配置)
打开 entry/hvigorfile.ts,添加:
+ import { hapTasks, OhosHapContext, OhosPluginId, Target } from '@ohos/hvigor-ohos-plugin';
+ import { HvigorPlugin, HvigorNode, getNode } from '@ohos/hvigor';
+ import { opSqlitePlugin } from './oh_modules/@react-native-ohos/op-sqlite/hvigorfile.ts'; //此处根据实际路径来进行配置
+const path = require('path');
+const rootRNPackagePath = path.join(__dirname, '../package.json'); //此处根据实际 package 路径来进行配置
export default {
system: hapTasks,
+ plugins: [opSqlitePlugin(rootRNPackagePath)]
}运行
点击右上角的 sync 按钮
或者在终端执行:
cd entry
ohpm install然后编译、运行即可。
约束与限制
兼容性
要使用此库,需要使用正确的 React-Native 和 RNOH 版本。另外,还需要使用配套的 DevEco Studio 和手机 ROM。
本文档内容基于以下版本验证通过:
- RNOH: 0.82.1; SDK: HarmonyOS API Version 21 Release SDK; IDE: DevEco Studio 6.0.1.260; ROM: 6.0.0.130;
权限要求
- 应用需要访问网络(远程数据库 / libsql 同步场景)时,需申请网络权限。
在 YourProject/entry/src/main/module.json5 补上配置:
{
"module": {
"name": "entry",
"type": "entry",
···
"requestPermissions": [
+ { "name": "ohos.permission.INTERNET" },
]
}
}使用示例
下面的代码展示了这个库的基本使用场景:
[!WARNING] 使用时 import 的库名不变。
import React, { useEffect, useState } from 'react';
import {
SafeAreaView,
Text,
TouchableOpacity,
View,
} from 'react-native';
import {
open,
type DB,
Scalar,
HARMONY_DATABASE_PATH
} from '@op-engineering/op-sqlite';
export default function OpSqliteExample() {
const [sqliteVersion, setSqliteVersion] = useState<Scalar>('');
const handlePress = async () => {
try {
const db: DB = open({
name: 'helloDb.sqlite',
encryptionKey: 'test',
location: HARMONY_DATABASE_PATH
});
const res = await db.execute('SELECT sqlite_version();');
const version = res.rows[0]['sqlite_version()'];
setSqliteVersion(version);
} catch (error) {
setSqliteVersion('Error getting version');
}
};
return (
<SafeAreaView style={{ flex: 1, backgroundColor: '#fff' }}>
<View style={{ flex: 1, backgroundColor: '#fff' }}>
<TouchableOpacity
style={{ padding: 5 }}
onPress={handlePress}
>
<Text style={{ color: 'red' }}>
tap to {'openDB'}
</Text>
</TouchableOpacity>
<Text>{String(sqliteVersion)}</Text>
</View>
</SafeAreaView>
);
}使用说明
[!TIP] 以下示例中数据库路径需使用鸿蒙应用可访问的沙箱路径,可通过
getConstants()获取的HARMONY_DATABASE_PATH/HARMONY_FILES_PATH拼接。open时传入的location即为数据库存放目录。
打开/关闭数据库
import { open, getConstants, type DB } from '@op-engineering/op-sqlite';
const { HARMONY_DATABASE_PATH } = getConstants();
// 打开数据库,encryptionKey 为启用 sqlcipher 后的密钥
const db: DB = open({
name: 'helloDb.sqlite',
location: HARMONY_DATABASE_PATH,
encryptionKey: 'test',
});
// 异步打开(15.0.0+)
// const db = await openAsync({ name: 'helloDb.sqlite', location: HARMONY_DATABASE_PATH });
// 关闭数据库
db.close();执行 SQL(同步/异步)
// 异步执行(返回 Promise)
const res = await db.execute('SELECT * FROM users WHERE id = ?', [1]);
const row = res.rows[0];
const syncRes = db.executeSync('SELECT * FROM users WHERE id = ?', [1]);
// 只返回值数组
const rawRows = await db.executeRaw('SELECT * FROM users');事务
// 出错自动回滚
await db.transaction(async (tx) => {
await db.execute("INSERT INTO users (name) VALUES (?)", ['alice']);
await db.execute("INSERT INTO users (name) VALUES (?)", ['bob']);
});批量执行与预编译语句
// 批量执行
await db.executeBatch([
['INSERT INTO users (name) VALUES (?)', ['alice']],
['INSERT INTO users (name) VALUES (?)', ['bob']],
]);
// 预编译语句,可重复 bind/execute
const stmt = db.prepareStatement('SELECT * FROM users WHERE id = ?');
// stmt.bind(...); stmt.execute(); ...响应式查询
// 数据变更时回调
const unsubscribe = db.reactiveExecute({
query: 'SELECT * FROM users WHERE id = ?',
arguments: [1],
fireOn: [{ table: 'users' }],
callback: (response) => console.log('data changed', response),
});
// 不再需要时取消订阅
unsubscribe();远程数据库同步(libsql)
import { openSync } from '@op-engineering/op-sqlite';
// V15.0.0:将本地数据库同步到远程并打开
const db = openSync({
url: 'https://your-libsql-endpoint',
authToken: 'token',
name: 'remoteDb.sqlite',
location: HARMONY_DATABASE_PATH,
});
// 触发与远程副本同步
db.sync();[!WARNING] 启用 sqlcipher / libsql 需要在工程根目录
package.json的op-sqlite字段中配置,并通过opSqlitePlugin在构建期生效,运行时修改无效。可分别用isSQLCipher()/isLibsql()确认当前是否启用。
接口说明
[!TIP] "Platform"列表示该属性在原三方库上支持的平台。
[!TIP] "HarmonyOS Support"列为 yes 表示 HarmonyOS 平台支持该属性;no 则表示不支持;partially 表示部分支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
静态方法
| Name | Description | Type | Required | Platform | HarmonyOS Support |
| ---- | ----------- | ---- | -------- | -------- | ------------------ |
| getConstants | 返回各平台数据库/文件存储沙箱路径。 | () => {IOS_DOCUMENT_PATH,IOS_LIBRARY_PATH,ANDROID_DATABASE_PATH,ANDROID_FILES_PATH,ANDROID_EXTERNAL_FILES_PATH,HARMONY_DATABASE_PATH,HARMONY_FILES_PATH,} | no | all | yes |
| open | 打开数据库。encryptionKey 为使用 sqlcipher 所需的密钥字符串,启用 sqlcipher 后支持该参数。 | (options: {name: string;location?: string;encryptionKey?: string;}) => DB; | no | all | yes |
| openAsync | open() 的异步版本。 | (params: {name: string; location?: string; encryptionKey?: string;}) => Promise; | no | all | yes |
| openSync | 将本地数据库同步到远程数据库并打开。 | (params: {url?: string; authToken?: string; name?: string; location?: string; libsqlSyncInterval?: number; libsqlOffline?: boolean; encryptionKey?: string; remoteEncryptionKey?: string;}) => DB | no | all | yes |
| openRemote | 打开远程数据库。 | (options: { url: string; authToken: string }) => DB; | no | all | yes |
| moveAssetsDatabase | 将数据库拷贝到指定路径。 | async (args: {filename: string;path?: string;overwrite?: boolean;}) => Promise | no | all | yes |
| isSQLCipher | 是否启用 SQLCipher 加密。 | () => boolean; | no | all | yes |
| isLibsql | 是否启用 libsql。 | () => boolean; | no | all | yes |
| isTurso | 是否为 turso 后端。 | () => boolean; | no | all | yes |
| isIOSEmbedded | 是否使用 iOS 内置 sqlite。 | () => boolean; | no | all | yes |
| isIOSEmbeeded | 是否使用 iOS 内置 sqlite。 | () => boolean; | no | all | yes |
DB
| Name | Description | Type | Required | Platform | HarmonyOS Support |
| ---- | ----------- | ---- | -------- | -------- | ------------------ |
| close | 关闭数据库。 | () => void; | no | all | yes |
| closeAsync | 异步关闭数据库。 | () => Promise; | no | all | yes |
| interrupt | 中止当前连接上的挂起操作,已开启事务会回滚。 | () => void; | no | all | yes |
| delete | 删除数据库文件。 | () => void; | no | all | yes |
| attach | 通过别名挂载其它数据库。 | (params: {secondaryDbFileName: string; alias: string; location?: string;}) => void; | no | all | yes |
| detach | 通过别名卸载挂载的数据库。 | (alias: string) => void; | no | all | yes |
| transaction | 通过事务操作数据库,出错自动回滚。 | (fn: (tx: Transaction) => Promise) => Promise; | no | all | yes |
| execute | 执行 SQL 语句。 | (query: string, params?: Scalar[]) => Promise; | no | all | yes |
| executeSync | 同步执行 SQL,阻塞 UI 线程,事务内不可用,需谨慎使用。 | (query: string, params?: Scalar[]) => QueryResult | no | all | yes |
| executeAsync | execute 的异步别名(drizzleORM 兼容)。 | (query: string, params?: Scalar[]) => Promise; | no | all | yes |
| executeWithHostObjects | 返回 HostObject 的查询语句,大数据查询快但字段访问慢。 | (query: string, params?: Scalar[]) => Promise; | no | all | yes |
| executeBatch | 批量执行多条语句。 | (commands: SQLBatchTuple[]) => Promise; | no | all | yes |
| executeRaw | 只返回值数组。 | (query: string, params?: Scalar[]) => Promise<any[]>; | no | all | yes |
| executeRawSync | executeRaw 的同步版本,阻塞 JS 线程。 | (query: string, params?: Scalar[]) => any[]; | no | all | yes |
| executeRawAsync | executeRaw 别名(drizzleORM 兼容)。 | (query: string, params?: Scalar[]) => Promise<any[]>; | no | all | yes |
| loadFile | 加载本地 SQL 文件。 | (location: string) => Promise; | no | all | yes |
| updateHook | 数据库更新钩子回调。 | (callback?:((params: {table: string;operation: UpdateHookOperation;row?: any;rowId: number;}) => void) | null) => void; | no | all | yes |
| commitHook | 事务提交钩子回调。 | (callback?: (() => void) | null) => void; | no | all | yes |
| rollbackHook | 事务回滚钩子回调。 | (callback?: (() => void) | null) => void; | no | all | yes |
| prepareStatement | 预编译语句,可重复 bind/execute。 | (query: string) => PreparedStatement; | no | all | yes |
| loadExtension | 加载 sqlite 运行时扩展。 | (path: string, entryPoint?: string) => void; | no | all | yes |
| getDbPath | 获取数据库文件路径。 | (location?: string) => string; | no | all | yes |
| reactiveExecute | 响应式查询,数据变更时回调。 | (params: {query: string;arguments: any[];fireOn: {table: string;ids?: number[];}[];callback: (response: any) => void;}) => () => void; | no | all | yes |
| sync | 触发与远程副本同步。 | () => void | no | all | yes |
| setReservedBytes | 设置 sqlite 保留字节数。 | (reservedBytes: number) => void; | no | all | yes |
| getReservedBytes | 读取 sqlite 保留字节数。 | () => number; | no | all | yes |
| flushPendingReactiveQueries | 刷新挂起的响应式查询队列。 | () => Promise; | no | all | yes |
遗留问题
无
其他
无
目录结构
/rntpc_op-sqlite # 项目根目录
├── harmony # 鸿蒙适配代码
│ └─ rn_op_sqlite.har # har 包
│ └─ rn_op_sqlite # 鸿蒙适配核心代码
│ └─ index.ets # 鸿蒙适配代码入口
│ └─ ts.ets # ArkTS 侧类型导出入口
│ └─ libs # 原生 so 库
│ └─ src/main
│ └─ ets
│ └─ RNOpSqliteTurboModule.ets # 鸿蒙侧 TurboModule 实现
│ └─ RNOpSqlitePackage.ets # 鸿蒙侧 Package
│ └─ cpp
│ └─ RNOpSqliteTurboModule.cpp/.h # C++ 侧 TurboModule 实现
│ └─ RNOpSqlitePackage.h # C++ 侧 Package
│ └─ generated # codegen 生成代码
│ └─ thirdparty # sqlite 第三方库
├── src # RN 代码
│ └─ index.ts # 入口文件
│ └─ NativeOPSQLite.ts # codegen TurboModule 规范定义
│ └─ types.ts # 类型文件
│ └─ functions.ts # 功能文件
├── example # 示例工程
├── README.md # 中文文档
├── README_en.md # 英文文档贡献代码
使用过程中发现任何问题都可以提交 Issue,当然,也非常欢迎提交 PR 。
开源协议
本项目基于 The MIT License (MIT) ,请自由地享受和参与开源。
