前言:
在app开发过程中,关系型数据库基本都会用到,纯血鸿蒙的关系型数据库底层也是sqllite,只不过纯血鸿蒙用的是ArtTS语法写的。本章就讲解下如何用ArtTS语法来进行关系型数据库的创建与升级。
一、基本使用方法
主要分3个步骤
(1)定义数据库的配置
(2)获取数据库的实例对象rdbStore
(3)根据数据库版本号来执行不同的sql
import { common } from '@kit.AbilityKit';
import { relationalStore } from '@kit.ArkData';
export class DBTest {
/**
* 1、定义数据库配置文件
* 2、获取数据库实例对象rdbStore
* 3、根据版本号执行不同sql
*
* @param context
*/
async createOrUpdate(context: common.UIAbilityContext) {
// 1、定义数据库配置文件
const config: relationalStore.StoreConfig = {
name: "rdbTest.db",
securityLevel: relationalStore.SecurityLevel.S2, // 数据库安全级别
encrypt: false // 数据库是否加密
}
// 2、获取数据库实例对象rdbStore
let rdbStore = await relationalStore.getRdbStore(context, config);
// 3、根据版本号执行不同sql
if (rdbStore.version === 0) {
rdbStore.executeSql('CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER)')
rdbStore.version = 1
}
if (rdbStore.version === 1) {
rdbStore.executeSql('ALTER TABLE EMPLOYEE ADD COLUMN sex Text');
rdbStore.version = 2
}
if (rdbStore.version === 2) {
rdbStore.executeSql('ALTER TABLE EMPLOYEE ADD COLUMN ADDRESS TEXT');
rdbStore.version = 3
}
}
}
securityLevel配置:
鸿蒙系统对于应用数据的存放分为了el1~el5目录,安全级别逐次提高,如果不涉及高敏感数据可以存在el1和el2目录,也就是securityLevel.S1和securityLevel.S2的配置。如果涉及高敏感数据,可以放在el3目录或者el4目录,这两个目录的区别就是在锁屏场景下,el3可以创建文件,但不可以读取文件,锁屏场景会读取失败。而el4目录是既不可以创建也不能读取。el1和el2目录锁屏场景下应用可以正常读取。
encrypt配置:
该配置很直观就是是否给数据库加密,如果是true,相当于整个数据库文件是加密状态。如果数据库中存在敏感个人数据,可以设置为true。但是不影响使用接口获取数据。无论加密还是不加密,接口访问数据的方式都一样,都是通过rdbStore对象访问。只不过数据库文件无法用一些sqllite工具直接查看。如果想用sqllite工具查看数据库文件,需要将endrypt设置为false才行。
二、更优雅的实现数据的升级
考虑到随着app版本迭代,数据库升级可能会越来越多,版本的if判断也会越来越多,不利于代码的维护和扩展,可以将升级操作抽取为多态类。
完整的实现如下:
定义一个IRdbUpgrade接口,每次数据库需要升级时,新增一个实现类,无需修改主流程代码。
主流程代码:
import { common } from '@kit.AbilityKit';
import { relationalStore } from '@kit.ArkData';
import { IRdbUpgrade } from './IRdbUpgrade';
import { V2RdbUpgrade } from './V2RdbUpgrade';
import { V3RdbUpgrade } from './V3RdbUpgrade';
export class DBTest2 {
// 最新的目标版本
private targetVersion = 3;
async createOrUpdate(context: common.UIAbilityContext) {
// 1、定义数据库配置文件
const config: relationalStore.StoreConfig = {
name: "rdbTest.db",
securityLevel: relationalStore.SecurityLevel.S2, // 数据库安全级别
encrypt: false // 数据库是否加密
}
// 2、获取数据库实例对象rdbStore
let rdbStore = await relationalStore.getRdbStore(context, config);
// 3、根据版本号执行不同sql
switch (rdbStore.version) {
case 0:
// app新安装场景,创建表
this.doCreate(rdbStore);
break;
default:
// app升级场景,升级数据库
this.doUpgrade(rdbStore);
}
}
async doCreate(rdbStore: relationalStore.RdbStore) {
try {
rdbStore.beginTransaction(); // 开启事务
await rdbStore.executeSql('xxxxx');
await rdbStore.executeSql('xxxxx');
await rdbStore.executeSql('xxxxx');
// 修改数据库版本
rdbStore.version = this.targetVersion;
rdbStore.commit();
} catch (e) {
rdbStore.rollBack();
}
}
upgradeOper: IRdbUpgrade[] = [new V2RdbUpgrade(), new V3RdbUpgrade()];
async doUpgrade(rdbStore: relationalStore.RdbStore) {
// 过滤出大于当前版本的升级类,并把所有升级类按照版本从小到大排序,一次执行升级操作
let sortUpgradeOper = this.upgradeOper
.sort((pre, post) => pre.getVersion() - post.getVersion())
.filter((upgrade) => upgrade.getVersion() > rdbStore.version);
try {
rdbStore.beginTransaction();
for (let i = 0; i< sortUpgradeOper.length; i++) {
await sortUpgradeOper[i].doUpgrade(rdbStore);
}
rdbStore.version = this.targetVersion;
rdbStore.commit();
} catch (e) {
rdbStore.rollBack();
}
}
}
IRdbUpgrade接口:
import { relationalStore } from '@kit.ArkData';
export interface IRdbUpgrade {
// 做数据库升级操作
doUpgrade(rdbStore: relationalStore.RdbStore): Promise<void>;
// 返回当前操作的数据库版本
getVersion(): number;
}
版本2的实现类:
import { IRdbUpgrade } from './IRdbUpgrade';
import relationalStore from '@ohos.data.relationalStore';
/**
* 实现数据库版本1升级到版本2的数据库操作
*/
export class V2RdbUpgrade implements IRdbUpgrade {
async doUpgrade(rdbStore: relationalStore.RdbStore): Promise<void> {
await rdbStore.executeSql('xxxx');
await rdbStore.executeSql('xxxx');
await rdbStore.executeSql('xxxx');
}
getVersion(): number {
return 2;
}
}
版本3的实现类:
import { IRdbUpgrade } from './IRdbUpgrade';
import relationalStore from '@ohos.data.relationalStore';
/**
* 实现数据库版本2升级到版本3的数据库操作
*/
export class V3RdbUpgrade implements IRdbUpgrade {
async doUpgrade(rdbStore: relationalStore.RdbStore): Promise<void> {
await rdbStore.executeSql('xxxx');
await rdbStore.executeSql('xxxx');
await rdbStore.executeSql('xxxx');
}
getVersion(): number {
return 3;
}
}
如果后续有新增升级操作,步骤如下:
(1)新增一个实现类继承IRdbUpgrade接口
(2)并将targetVersion加1
(3)在数组upgradeOper: IRdbUpgrade[] = [new V2RdbUpgrade(), new V3RdbUpgrade()];中将新加的实现类加入数组中。