DEV Community

Studotie Handwer
Studotie Handwer

Posted on

How do you put data on the storage?

In modern operating systems, data persistence is a critical concern. Especially on mobile and IoT devices, developers are highly focused on how to efficiently, quickly, and securely persist data to disk to ensure application stability and data reliability.

With the continuous evolution of HarmonyOS, its data persistence solutions have become increasingly rich. The commonly used persistence technologies now include MMKV, relational databases, and distributed key-value (KV) storage.


1. MMKV: Lightweight and Efficient Storage

What is MMKV?

MMKV (Memory Mapped Key-Value) is a lightweight and high-performance local data storage solution. It uses memory-mapped files to achieve efficient disk storage. MMKV’s core strengths are efficiency and low memory usage, making it especially suitable for storing small, frequently accessed key-value data.

Using MMKV for Data Persistence

MMKV is available via ohpm and allows developers to easily persist data to disk. With ArkTS APIs, you can:

  • Store simple data types like strings, integers, booleans, etc.
  • Support multi-threaded read/write with consistency and thread safety.
  • Provide encrypted storage for securing sensitive data.

Advantages of MMKV

  • High Performance: Based on memory-mapped file technology, reducing IO frequency and improving speed.
  • Ease of Use: ArkTS offers simple APIs for developers to read/write data with ease.
  • Encryption Support: Data can be encrypted with minimal configuration to ensure security.

Example Code:

let mmkv = MMKV.defaultMMKV(); mmkv.encodeBool('bool', true); console.info('bool = ', mmkv.decodeBool('bool')); mmkv.encodeInt32('int32', Math.pow(2, 31) - 1); console.info('max int32 = ', mmkv.decodeInt32('int32')); mmkv.encodeInt64('int', BigInt(2**63) - BigInt(1)); console.info('max int64 = ', mmkv.decodeInt64('int')); let str: string = 'Hello OpenHarmony from MMKV'; mmkv.encodeString('string', str); console.info('string = ', mmkv.decodeString('string')); let arrayBuffer: ArrayBuffer = StringToArrayBuffer('Hello OpenHarmony from MMKV with bytes'); mmkv.encodeBytes('bytes', arrayBuffer); let bytes = mmkv.decodeBytes('bytes'); console.info('bytes = ', ArrayBufferToString(bytes)); let arr = new Uint8Array([0, 255, 1, 255]); mmkv.encodeTypedArray('uint8-array', arr); let newUI8Arr = kv.decodeUint8Array('uint8-array'); console.info('uint8-array = ', newUI8Arr); 
Enter fullscreen mode Exit fullscreen mode

2. rdbStore: Relational Database Storage

What is rdbStore?

rdbStore is a relational database storage solution provided by HarmonyOS. It is based on SQLite and is suited for scenarios that require storage of complex relational data.

For example:

  • A class of students with names, student IDs, and grades.
  • Company employee records with names, employee IDs, positions, etc.

Since the data is highly structured and relational, it is best stored using a relational database.


Using rdbStore

Before using, you first need to get a store instance:

relationalStore.getRdbStore(this.context, STORE_CONFIG, (err: BusinessError, rdbStore: relationalStore.RdbStore) => { store = rdbStore; if (err) { console.error(`Get RdbStore failed, code is ${err.code}, message is ${err.message}`); return; } console.info('Get RdbStore successfully.'); }); 
Enter fullscreen mode Exit fullscreen mode

STORE_CONFIG includes information like the database file name, security level, and whether encryption is enabled.


Once you get the store, you can perform standard CRUD operations (Create, Read, Update, Delete) via its API:

Initialize a Table
async initTable(context: Context, setVersion: boolean = false) { try { let store = await this.getRdbStore(context) if (store.version === 0) { await store.executeSql(this.sqlCreateTable) if (setVersion) store.version = DatabaseConsts.STORE_VERSION } } catch (e){ Logger.error(this.TAG, `Init table ${this.tableName} failed: ${e}`) throw Error(e) } } 
Enter fullscreen mode Exit fullscreen mode
Insert Data
async insertData(context: Context, data: ValuesBucket) { try { let store = await this.getRdbStore(context) let res = await store.insert(this.tableName, data) Logger.info(this.TAG, `Insert data completed, ret = ${res}`) } catch (e) { Logger.error(this.TAG, `Insert data failed: ${e}`) throw Error(e) } } 
Enter fullscreen mode Exit fullscreen mode
Update Data
async updateData(context: Context, predicate: relationalStore.RdbPredicates, data: ValuesBucket): Promise<number> { return new Promise((resolve, reject) => { this.getRdbStore(context) .then((store) => store.update(data, predicate)) .then((ret) => { Logger.info(this.TAG, `Update data completed, ret = ${ret}`) resolve(ret) }).catch((e: BusinessError) => { Logger.error(this.TAG, `Update data failed, err = ${e}`) reject(e) }); }); } 
Enter fullscreen mode Exit fullscreen mode
Delete Data
async deleteData(context: Context, predicate: relationalStore.RdbPredicates): Promise<number> { return new Promise((resolve, reject) => { this.getRdbStore(context) .then((store) => store.delete(predicate)) .then((ret) => { Logger.info(this.TAG, `Delete data completed, ret = ${ret}`) resolve(ret) }).catch((e: BusinessError) => { Logger.error(this.TAG, `Delete data failed, err = ${e}`) reject(e) }); }); } 
Enter fullscreen mode Exit fullscreen mode
Query Data
async queryData(context: Context, predicate: relationalStore.RdbPredicates): Promise<relationalStore.ResultSet> { return new Promise((resolve, reject) => { this.getRdbStore(context) .then((store) => store.query(predicate)) .then((result) => { Logger.info(this.TAG, `Query data completed`) resolve(result) }) .catch((e: BusinessError) => { Logger.error(this.TAG, `Query data failed, err = ${e}`) reject(e) }); }); } 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)