核心API
@ohos.data.relationalStore API 9+
數據庫
數據庫是存儲和管理數據的系統
數據庫(Database)是一個以特定方式組織、存儲和管理數據的集合,通常用于支持各種應用程序和系統的運行。它不僅是存放數據的倉庫,還通過一定的規則和結構來確保數據的高效查詢和管理。?
數據庫的核心特點
- ?數據存儲?:數據庫可以存儲大量數據,從百萬條到上億條不等,且數據按特定規則組織,以提高查詢效率。
- ?數據管理?:數據庫通過數據庫管理系統(DBMS)進行統一管理,確保數據的安全性、完整性和一致性。
- ?數據共享?:數據庫支持多用戶同時訪問,且數據可以被多個應用程序共享和使用。
數據庫的常見類型
- ?關系型數據庫?:基于關系模型,數據以表格形式存儲,支持SQL語言進行復雜查詢,如MySQL、Oracle等。
- ?非關系型數據庫(NoSQL)?:適用于非結構化或半結構化數據,具有更好的橫向擴展能力,如MongoDB、Redis等。
鴻蒙的關系型數據庫用法?@ohos.data.relationalStore?API 9+
關系型數據庫(Relational Database,RDB)是一種基于關系模型來管理數據的數據庫。關系型數據庫基于SQLite組件提供了一套完整的對本地數據庫進行管理的機制,對外提供了一系列的增、刪、改、查等接口,也可以直接運行用戶輸入的SQL語句來滿足復雜的場景需要。支持通過ResultSet.getSendableRow方法獲取Sendable數據,進行跨線程傳遞。
為保證插入并讀取數據成功,建議一條數據不要超過2M。超出該大小,插入成功,讀取失敗。
大數據量場景下查詢數據可能會導致耗時長甚至應用卡死,如有相關操作可參考文檔批量數據寫數據庫場景,且有建議如下:
- 單次查詢數據量不超過5000條。
- 在TaskPool中查詢。
- 拼接SQL語句盡量簡潔。
- 合理地分批次查詢。
該模塊提供以下關系型數據庫相關的常用功能:
- RdbPredicates: 數據庫中用來代表數據實體的性質、特征或者數據實體之間關系的詞項,主要用來定義數據庫的操作條件。
- RdbStore:提供管理關系數據庫(RDB)方法的接口。
- ResultSet:提供用戶調用關系型數據庫查詢接口之后返回的結果集合。
- Transaction:提供管理事務對象的接口。
使用數據庫封裝一個數據庫工具,用于存儲錄音
在之前的文章中,我們完成了一些錄音和播放的功能,但是目前只能現錄現播。如果我們想把錄音數據存起來,這時候用關系型數據庫就比較合適。
- 首先我們要準備好要存儲的數據類型,并且繼承數據庫提供的“桶”類型ValuesBucket
- 要有一個初始化數據庫的方法,獲取上下文,并判斷是否獲取到上下文
- 如果數據庫不存在就創建relationalStore.getRdbStore,存在就不創建
- store.executeSql在數據庫中創建或打開表,SQL語句可以去用AI生成
- 需要增刪改查四個方法
- 增:直接傳入要添加的數據
- 刪:創建謂詞對象,傳入Id,根據id找到行,然后刪除
- 改:創建謂詞對象,傳入整個對象,找到修改行,更新
- 查:創建謂詞對象,傳入user_Id,采用游標移動取值,循環到沒有下一行為止,每一次循環都在數組中追加當前的行,最后返回一個數組。
import { relationalStore, ValuesBucket } from "@kit.ArkData"
import { InterviewAudioItem } from "../../models"export interface InterviewAudioItem extends ValuesBucket {id: number | nulluser_id: stringname: stringpath: stringduration: numbersize: numbercreate_time: number
}class AudioDB {store?: relationalStore.RdbStoretableName = 'success_audio'// 1. 初始化數據庫和數據庫表async initStore() {// 1.0 獲取上下文const ctx = AppStorage.get<Context>('context')if (ctx) {// 1.1 創建數據庫// 有則獲取, 沒有則創建const store = await relationalStore.getRdbStore(ctx, {name: 'interview_audio.db',securityLevel: relationalStore.SecurityLevel.S1})// 1.2 在數據庫中創建一張數據庫表store.executeSql(`CREATE TABLE IF NOT EXISTS ${this.tableName} (id INTEGER PRIMARY KEY AUTOINCREMENT,user_id TEXT NOT NULL,name TEXT NOT NULL,path TEXT NOT NULL,duration INTEGER NOT NULL,size INTEGER NOT NULL,create_time INTEGER NOT NULL)`)this.store = store}}// 2. 添加一條音頻數據async insert(item: InterviewAudioItem) {if (this.store) {const rowId = await this.store.insert(this.tableName, item)if (rowId === undefined || rowId === -1) {return Promise.reject('插入音頻數據失敗')} else {return Promise.resolve()}}}// 3. 刪除一條音頻數據async delete(audioId: number) {if (this.store) {const predicates = new relationalStore.RdbPredicates(this.tableName)predicates.equalTo('id', audioId)const rowId = await this.store.delete(predicates)if (rowId === undefined || rowId === -1) {return Promise.reject('刪除音頻數據失敗')} else {return Promise.resolve()}}}// 4. 修改一條音頻數據async update(item: InterviewAudioItem) {if (this.store) {const predicates = new relationalStore.RdbPredicates(this.tableName)predicates.equalTo('id', item.id)const rowId = await this.store.update(item, predicates)if (rowId === undefined || rowId === -1) {return Promise.reject('修改音頻數據失敗')} else {return Promise.resolve()}}}// 5. 根據用戶id查詢用戶所有的錄音數據async query(userId: string) {if (this.store) {// 1. 創建一個基于查詢條件的謂詞對象const predicates = new relationalStore.RdbPredicates(this.tableName)predicates.equalTo('user_id', userId)// 2. 執行數據庫查詢得到結果集const resultSet = await this.store.query(predicates)if (!resultSet) {return Promise.reject('query fail')}// 3. 采用游標移動取值const list: InterviewAudioItem[] = []// 3.1 如果有下一行, 則繼續循環while (resultSet?.goToNextRow()) {list.push(resultSet.getRow() as InterviewAudioItem)}// 3.2 關閉查詢結果集resultSet.close()return Promise.resolve(list)}return Promise.reject('暫無數據庫')}
}export const audioDB = new AudioDB()
這樣一個完整功能的數據庫工具就創建好了,那么我們就直接去把錄音存到數據庫中吧!
在錄音頁面中使用數據庫保存數據
首先在頁面開始時初始化數據庫
async aboutToAppear() {await this.getPermission()// 2. 初始化數據庫await audioDB.initStore()}
?初始化完成可以在設備管理器中看到三個數據庫相關文件
在錄制開始的函數中,我們記錄下開始時間
在點擊結束錄制的時候,我們再額外調用一個方法,傳入音頻類型的項,調用數據庫方法插入數據庫中。
// 存入數據庫方法async onRecordEnd(item: InterviewAudioItem) {await audioDB.insert(item)AlertDialog.show({ message: '錄音保存成功' })}Button('停止錄制').onClick(() => {this.stopRecord()// 以只讀的方式根據路徑打開文件const file = fileIo.openSync(this.filePath, fileIo.OpenMode.READ_ONLY)const stat = fileIo.statSync(file.fd)this.onRecordEnd({id: null,user_id: auth.getUser().id,name: dayjs().format('YYYY年MM月DD日_hh點mm分ss秒'),path: this.filePath || '',duration: Date.now() - this.startTime,create_time: Date.now(),size: stat.size})promptAction.showToast({ message: '停止錄制' })})
?點擊開始錄音錄制一段時間,然后結束錄制
這樣一條數據就被插入了數據庫表中,對比數據庫文件發現,確實比之前大了,就說明已經插入完成,因為沒有可視化打開數據庫的工具,所有無法具體查看數據表的內容。