使用sqlite 存储非敏感数据用sqlite进行缓存,提高用户和网络的体验,系统性能。
了解下sqlite
鸿蒙开发主要使用SQLite数据库。SQLite是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,其特点就是小型、快速、自给自足、高度可靠、全功能。 SQLite具有以下优势:
- 1、轻量级,便于移植;
- 2、无需服务器;
- 3、零配置,无需安装和管理;
- 4、支持数据库事务。 同时,SQLite在鸿蒙系统中也会有一些特殊的应用方式和优化策略。
一、为什么选择SQLite
SQLite是一种嵌入式SQL数据库引擎,不像常见的SQL数据库服务器,如MySQL、Oracle、PostgreSQL等需要单独的服务器进程,SQLite不需要配置和启动服务,一个轻量级的磁盘文件就可以轻松处理。在鸿蒙系统中, SQLite可以为每个应用提供独立的数据库,有效隔离了数据,保证了数据的安全性和隐私性。 SQLite的轻量级和高效性使其在嵌入式设备中的应用非常广泛
二、SQLite在鸿蒙中的应用
在鸿蒙系统中,SQLite主要用于应用的数据存储和管理。开发者可以通过SQLite的API进行数据库的创建、查询、更新和删除等操作。同时,鸿蒙系统还提供了一些特有的SQLite接口,如分布式数据管理接口,以支持分布式设备间的数据同步。 在实际的开发过程中,SQLite的使用非常简单。首先,开发者需要通过SQLite的API创建一个数据库,然后就可以通过SQL语句对数据库进行操作。所有的操作都可以通过一个简单的API完成,无需复杂的配置和管理。
三、鸿蒙对SQLite的优化 鸿蒙系统针对SQLite也进行了一些优化。首先,鸿蒙系统优化了SQLite的磁盘IO性能,通过改进磁盘IO调度算法,提高了SQLite的读写性能。其次,鸿蒙系统还优化了SQLite的内存使用,通过改进内存管理策略,降低了SQLite的内存占用,使其更适合在资源受限的设备上运行。 鸿蒙系统还为SQLite提供了一套完整的测试框架,包括单元测试、集成测试和系统测试,以保证SQLite的稳定性和可靠性。 总的来说,SQLite是鸿蒙系统的理想选择,其轻量级和高效性完全符合鸿蒙的定位。同时,鸿蒙系统还针对SQLite进行了一些优化,使其在鸿蒙系统上的性能更优,为鸿蒙开发者提供了一个便捷、高效的数据管理工具。
四、本案例我们的需求
- 1、我们做一个用户注册用户-存储在数据库,不使用网络请求
- 2、登录能正常登录,通过本地数据库查询用户是否存在
- 3、需要使用到taskpool线程池,在非主线程进行数据处理提高性能和效率
- 4、不直接在page页面进行引用sqlitedb操作
通过本案例,你可以改造做你相关业务处理,很多场景都需要用到数据库,那么除了本地数据库以外,华为鸿蒙HarmonyOS Next还提供了云数据库。
在EntryAbility的onCreate进行初始化数据库
//初始化数据库
MyRdb.getInstance().initRdbStore(this.context)
注册页面demo完整代码
import Prompt from '@system.prompt'
import { UserModel } from '../../../model/UserModel';
import { taskPoolExecuteInsertUser,
taskPoolExecuteQueryUser,
taskPoolExecuteQueryUserCount } from '../../../task/RdbTaskPool';
@Entry
@Component
struct InstertDbPage {
@State message: string = 'Hello World';
@State mobile: string = '13800138000'
@State passWord: string = '1'
@State userName: string = 'alan'
@State surePassWord: string = '1'
@State isShowProgress: boolean = false;
build() {
Column() {
// 标题栏
Row() {
Row() {
Text('用户注册')
.fontSize(20)
.fontWeight(600)
}.layoutWeight(1)
.justifyContent(FlexAlign.Center)
Blank()
.width(20)
}
.width('100%')
.height(40)
.justifyContent(FlexAlign.SpaceBetween)
// 登录框
Column() {
Row() {
Text('手机号')
.fontSize(14)
TextInput({ placeholder: '请输入手机号', text: this.mobile })
.borderRadius(5)
.type(InputType.PhoneNumber)
.backgroundColor('#f5f5f5')
.layoutWeight(1)
.onChange(value => {
this.mobile = value
})
}.width('90%')
.padding(3)
.borderRadius(6)
.backgroundColor('#f5f5f5')
Row() {
Text('姓 名')
.fontSize(14)
TextInput({ placeholder: '请输入姓名', text: this.userName })
.borderRadius(5)
.backgroundColor('#f5f5f5')
.layoutWeight(1)
.onChange(value => {
this.userName = value
})
}.width('90%')
.padding(3)
.borderRadius(6)
.backgroundColor('#f5f5f5')
.margin({ top: 10 })
Row() {
Text('密 码')
.fontSize(14)
TextInput({ placeholder: '请输入密码', text: this.passWord })
.type(InputType.Password)
.borderRadius(5)
.backgroundColor('#f5f5f5')
.layoutWeight(1)
.onChange(value => {
this.passWord = value
})
}
.width('90%')
.padding(3)
.borderRadius(6)
.backgroundColor('#f5f5f5')
.margin({ top: 10 })
Row() {
Text('确认密码')
.fontSize(14)
TextInput({ placeholder: '请输入确认密码', text: this.surePassWord })
.type(InputType.Password)
.borderRadius(5)
.backgroundColor('#f5f5f5')
.layoutWeight(1)
.onChange(value => {
this.surePassWord = value
})
}
.width('90%')
.padding(3)
.borderRadius(6)
.backgroundColor('#f5f5f5')
.margin({ top: 10 })
Row() {
Button('注册')
.commonButton()
.fontColor(Color.White)
.backgroundColor('#0ab906')
.onClick( async () =>
{
this.register()
})
}
.width('90%')
.margin({ top: 30 })
}.width('100%')
.margin({ top: 20 })
}.width('100%')
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.SpaceBetween)
}
private async register(){
if (this.mobile.trim() == '') {
Prompt.showToast({
message: '请输入手机号'
})
return
}
if (this.userName.trim() == '') {
Prompt.showToast({
message: '请输入用户名'
})
return
}
if (this.passWord.trim() == '') {
Prompt.showToast({
message: '请输入密码'
})
return
}
if (this.surePassWord.trim() == '') {
Prompt.showToast({
message: '请输入确认密码'
})
return
}
//loadingUtil.showLoading()
taskPoolExecuteQueryUserCount(getContext(this),this.mobile).then(async (result:number)=>{
if(result > 0){
this.showToast('该手机号注册了')
//loadingUtil.hideLoading()
return
}
await taskPoolExecuteInsertUser(getContext(this),this.userName,this.mobile,this.passWord)
this.showToast('注册成功')
await taskPoolExecuteQueryUser(getContext(this),this.mobile).then(async (result:Array<UserModel>) =>{
console.log(`result:${JSON.stringify(result)}`)
})
})
}
showToast(content:string){
Prompt.showToast({
message: content
})
}
}
@Extend(Button) function commonButton() {
.width('100%')
.height(35)
.fontSize(14)
.type(ButtonType.Normal)
.borderRadius(3)
}
MyRdb工具类代码
import { relationalStore, ValuesBucket } from '@kit.ArkData'
import { common } from '@kit.AbilityKit'
import { UserModel } from '../model/UserModel'
export class MyRdb {
private static instance: MyRdb | undefined = undefined
private rdbStore: relationalStore.RdbStore | undefined = undefined
private TABLE_USER: string = 't_user'
/**
*静态方法,用于获取数据库连接实例
* @returns数据库实例
* */
public static getInstance(): MyRdb {
if (!MyRdb.instance) {
MyRdb.instance = new MyRdb()
}
return MyRdb.instance
}
/**
* 初始化数据
* @param context
* @returns
*/
public async initRdbStore(context: common.Context): Promise<void> {
console.log('initdb ', 'init redbStore begin')
if (!context) {
console.error('inidb', 'init redbstore context is invalid')
}
if (this.rdbStore) {
console.info('initdb ', 'redbStore is exist')
return
}
const config: relationalStore.StoreConfig = {
name: 'mydb.db', //数据库名
securityLevel: relationalStore.SecurityLevel.S1 //安全级别 s1最低
}
try {
this.rdbStore = await relationalStore.getRdbStore(context, config)
console.info('initRdbStore', 'getRdbStore succeed');
await this.createTable()
} catch (err) {
console.error('inidb', `getRedbstore failed,error:${err}`)
}
}
private async createTable(): Promise<void> {
console.info('createTable', 'create table begin')
try {
//初始化sql语句
const userSql = `CREATE TABLE IF NOT EXISTS ${this.TABLE_USER}(id INTEGER PRIMARY KEY AUTOINCREMENT,nickname TEXT NOT NULL, mobile TEXT NOT NULL,password TEXT NULL)`
console.info("createTable",userSql)
//执行sql语句
if (this.rdbStore != undefined) {
await this.rdbStore.executeSql(userSql)
console.info('createTable', 'create table succeed')
}
} catch (e) {
console.error('createTable', `create table failed, err: ${e}`)
}
}
public async queryUserCount(context: common.Context,mobile: string):Promise<number>{
console.info('queryUser', 'queryUser begin');
if (!context) {
console.info('queryUser','context is null or undefined')
return 0
}
if (!this.rdbStore) {
console.info('queryUser','query rdbstore is null')
await this.initRdbStore(context)
}
//构建查询条件
let predicates = new relationalStore.RdbPredicates(this.TABLE_USER)
predicates.equalTo('mobile', mobile)
//查询(如果是真正的企业项目,数据量大的话不能直接同步查,会很耗时,要用query方法)
let resultSet:relationalStore.ResultSet = await this.rdbStore!!.query(predicates)
//获取数据条数
const rowCount = resultSet.rowCount
//释放数据集的内存
resultSet.close()
return rowCount
}
/**
* 查询
*/
public async queryUserInfo(context:common.Context,mobile: string):Promise<Array<UserModel>>{
console.info('queryUser', 'queryUser begin');
if (!context) {
console.info('queryUser','context is null or undefined')
return []
}
if (!this.rdbStore) {
console.info('queryUser','query rdbstore is null')
await this.initRdbStore(context)
}
//构建查询条件
let predicates = new relationalStore.RdbPredicates(this.TABLE_USER)
if (predicates === null || predicates === undefined) {
console.info('queryUser','predicates is null or undefined');
return []
}
predicates.equalTo('mobile', mobile)
//查询(如果是真正的企业项目,数据量大的话不能直接同步查,会很耗时,要用query方法)
let resultSet = await this.rdbStore!!.query(predicates)
//this.rdbStore?.querySync() //同步查询
let list:Array<UserModel> = []
while (!resultSet.isAtLastRow) {
// 指针移动到下一行
resultSet.goToNextRow()
// 获取数据(一个字段一个字段获取)
let id = resultSet.getLong(resultSet.getColumnIndex('id'))
let nickname = resultSet.getString(resultSet.getColumnIndex('nickname'))
let mobile = resultSet.getString(resultSet.getColumnIndex('mobile'))
let password = resultSet.getString(resultSet.getColumnIndex('password'))
list.push({
id,nickname,mobile,password
})
}
//释放数据集的内存
resultSet.close()
console.info('mydb',`查询数据长度:${list.length}`)
return list
}
/**
*插入数据库
*/
public async insertUser(context: common.Context,nickname: string, mobile: string, password: string):Promise<void> {
console.info('insertUser', 'insertUser begin');
if (!context) {
console.info('insertUser', 'context is null or undefined')
return
}
if (!this.rdbStore) {
console.info('insertUser', 'insert rdbStore is null')
await this.initRdbStore(context)
}
const valueBucket: ValuesBucket = {
'nickname': nickname,
'mobile': mobile,
'password': password
}
//this.rdbStore?.insertSync() //建议异步操作数据
await this.rdbStore!!.insert(this.TABLE_USER,valueBucket, relationalStore.ConflictResolution.ON_CONFLICT_REPLACE)
}
}
export default MyRdb
RdbTaskPool 线程池代码,主要考虑在非主线程使用数据操作
import { common } from '@kit.AbilityKit'
import { MyRdb } from '../db/MyRdb'
import { UserModel } from '../model/UserModel'
import taskpool from '@ohos.taskpool'
export async function taskPoolExecuteQueryUser(context: common.Context, mobile: string):Promise<Array<UserModel>>{
try{
//queryUserInfo函数调用:需使用装饰器@Concurrent
let task: taskpool.Task = new taskpool.Task(queryUserInfo, context, mobile)
let result = await taskpool.execute(task) as UserModel[]
return result
} catch (err) {
console.error('taskPoolExecuteQueryUserInfo', 'error:' + JSON.stringify(err))
return []
}
}
export async function taskPoolExecuteInsertUser(context: common.Context, nickname: string, mobile: string, password: string):Promise<void> {
try{
//insertUser函数调用:需使用装饰器@Concurrent
let task: taskpool.Task = new taskpool.Task(insertUser, context, nickname, mobile, password)
await taskpool.execute(task)
}catch (err){
console.error('taskPoolExecuteInsertUser', 'error:'+ JSON.stringify(err))
}
}
@Concurrent
async function queryUserInfo(context: common.Context, mobile: string): Promise<Array<UserModel>> {
return await MyRdb.getInstance().queryUserInfo(context, mobile)
}
@Concurrent
async function insertUser(context: common.Context, nickname: string, mobile: string, password: string):Promise<void> {
return await MyRdb.getInstance().insertUser(context, nickname, mobile, password)
}
/**
* Concurrent实现任务的函数 统计
* @param context
* @param mobile
* @returns
*/
@Concurrent
async function queryUserCount(context: common.Context, mobile: string): Promise<number> {
return await MyRdb.getInstance().queryUserCount(context, mobile)
}
export async function taskPoolExecuteQueryUserCount(context: common.Context, mobile: string):Promise<number>{
try {
//queryUserCount函数调用:需使用装饰器@Concurrent
let task: taskpool.Task = new taskpool.Task(queryUserCount,context, mobile)
let result = await taskpool.execute(task) as number
return result
} catch (err) {
console.error('taskPoolExecuteQueryUserCount', 'error:' + JSON.stringify(err))
return 0
}
}
usermodel实体类
export class UserModel{
id?:number
nickname?: string
mobile?: string
password?: string
}
效果图如下:
日志中可以看到查询和插入的日志