
【鸿蒙HarmonyOS开发笔记】通用型工具封装之关系型数据库操作类的封装
开发中难免遇到操作关系型数据库的场景,但是原生的使用起来略显繁琐,此文封装一个通用的关系型数据库增删改查的工具类,只需要少量修改配置即可使用,大幅简化我们的开发成本,提高开发效率。
·
概述
开发中难免遇到操作关系型数据库的场景,但是原生的relationalStore
使用起来略显繁琐,此文封装一个通用的关系型数据库增删改查
的工具类,只需要少量修改配置
即可使用,大幅简化我们的开发成本,提高开发效率
完整代码在文章结尾,拿代码直接划到结尾即可
1.封装初始化数据库函数与建表函数
createTable
函数只需要传入建表SQL
语句即可,需要自行准备哦
// 操作的数据库名称,
const DB_FILENAME: string = 'OliannaWen.db'
class DbUtil {
// 使用变量来获取关系型数据库操作对象
rdbStore: relationalStore.RdbStore
// 初始化数据库
initDB(context: common.UIAbilityContext): Promise<void> {
let config: relationalStore.StoreConfig = {
// 数据库名称
name: DB_FILENAME,
// 数据库操作安全等级
securityLevel: relationalStore.SecurityLevel.S1
}
return new Promise<void>((resolve, reject) => {
// 获取关系型数据库操作对象
relationalStore.getRdbStore(context, config)
.then(rdbStore => {
this.rdbStore = rdbStore
// 记录日志
Logger.debug('rdbStore 初始化完成!')
resolve()
})
.catch(reason => {
Logger.debug('rdbStore 初始化异常', JSON.stringify(reason))
reject(reason)
})
})
}
// 创建表函数,传入创建表语句
createTable(createSQL: string): Promise<void> {
return new Promise((resolve, reject) => {
this.rdbStore.executeSql(createSQL)
.then(() => {
Logger.debug('创建表成功', createSQL)
resolve()
})
.catch(err => {
Logger.error('创建表失败,' + err.message, JSON.stringify(err))
reject(err)
})
})
}
一般来讲,我们都会在EntryAbility.ets
中去初始化数据库,调用DbUtil.initDB
传入context
即可
import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import DbUtil from '../common/utils/DbUtil';
import RecordModel from '../model/RecordModel'
import PreferenceUtyil from "../common/utils/PreferenceUtil"
export default class EntryAbility extends UIAbility {
async onCreate(want, launchParam) {
// 加载用户首选项
PreferenceUtyil.loadPreference(this.context)
// 初始化RDB工具
await DbUtil.initDB(this.context)
// 创建表
DbUtil.createTable(RecordModel.getCreateTableSql())
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
新增方法
一般来说,我们实际开发使用的实体字段和数据库并不一定是一致的,所以需要先构建映射关系来保证正确插入
export interface ColumnInfo{
// 实体字段
name: string
// 映射到数据库对应的字段
columnName: string
// 数据库字段类型
type: ColumnType
}
export enum ColumnType{
LONG,
DOUBLE,
STRING,
BLOB
}
使用前需要自行准备映射关系,例如
const COLUMNS: ColumnInfo[] = [
{name: 'id', columnName: 'id', type: ColumnType.LONG},
{name: 'typeId', columnName: 'type_id', type: ColumnType.LONG},
{name: 'itemId', columnName: 'item_id', type: ColumnType.LONG},
{name: 'amount', columnName: 'amount', type: ColumnType.DOUBLE},
{name: 'createTime', columnName: 'create_time', type: ColumnType.LONG}
]
然后我们实现新增的通用方法
// 建立insert方法的映射关系(实体数据插入到数据库的字段映射)
buildValueBucket(obj: any, columns: ColumnInfo[]): relationalStore.ValuesBucket {
let value = {}
columns.forEach(info => {
let val = obj[info.name]
if (typeof val !== 'undefined') {
value[info.columnName] = val
}
})
return value
}
// 新增方法,参数为表名称和新增对象
insert(tableName: string, obj: any, columns: ColumnInfo[]): Promise<number> {
return new Promise((resolve, reject) => {
// 1.构建新增数据
let value = this.buildValueBucket(obj, columns)
// 2.新增
this.rdbStore.insert(tableName, value, (err, id) => {
if (err) {
Logger.error('新增失败!', JSON.stringify(err))
reject(err)
} else {
Logger.debug('新增成功!新增id:', id.toString())
resolve(id)
}
})
})
}
删除方法比较简单,不做展开
// 删除方法,传入删除条件
delete(predicates: relationalStore.RdbPredicates): Promise<number> {
return new Promise((resolve, reject) => {
this.rdbStore.delete(predicates, (err, rows) => {
if (err) {
Logger.error('删除失败!', JSON.stringify(err))
reject(err)
} else {
Logger.debug('删除成功!删除行数:', rows.toString())
resolve(rows)
}
})
})
}
查询方法
查询方法略微麻烦,我们先按照条件查询出目标,因为relationalStore
返回的是结果集,所以我们需要自己再解析一边,代码如下
// 查询方法,传入查询条件,字段,返回解析后的结果
queryForList<T>(predicates: relationalStore.RdbPredicates, columns: ColumnInfo[]): Promise<T[]> {
return new Promise((resolve, reject) => {
this.rdbStore.query(predicates, columns.map(info => info.columnName), (err, result) => {
if (err) {
Logger.error('查询失败!', JSON.stringify(err))
reject(err)
} else {
Logger.debug('查询成功!查询行数:', result.rowCount.toString())
resolve(this.parseResultSet(result, columns))
}
})
})
}
// 解析结果集
parseResultSet<T> (result: relationalStore.ResultSet, columns: ColumnInfo[]): T[] {
// 1.声明最终返回的结果
let arr = []
// 2.判断是否有结果
if (result.rowCount <= 0) {
return arr
}
// 3.处理结果
while (!result.isAtLastRow) {
// 3.1.去下一行
result.goToNextRow()
// 3.2.解析这行数据,转为对象
let obj = {}
columns.forEach(info => {
let val = null
switch (info.type) {
case ColumnType.LONG:
val = result.getLong(result.getColumnIndex(info.columnName))
break
case ColumnType.DOUBLE:
val = result.getDouble(result.getColumnIndex(info.columnName))
break
case ColumnType.STRING:
val = result.getString(result.getColumnIndex(info.columnName))
break
case ColumnType.BLOB:
val = result.getBlob(result.getColumnIndex(info.columnName))
break
}
obj[info.name] = val
})
// 3.3.将对象填入结果数组
arr.push(obj)
Logger.debug('查询到数据:', JSON.stringify(obj))
}
return arr
}
完整代码
使用时修改 DB_FILENAME
,并且提供实体数据字段与数据库字段的映射关系数组
DbUtil.ts
import common from '@ohos.app.ability.common';
import relationalStore from '@ohos.data.relationalStore';
import { ColumnInfo, ColumnType } from '../bean/ColumnInfo';
import Logger from './Logger';
// 操作的数据库名称
const DB_FILENAME: string = 'OliannaWen.db'
class DbUtil {
// 使用变量来获取关系型数据库操作对象
rdbStore: relationalStore.RdbStore
// 初始化数据库
initDB(context: common.UIAbilityContext): Promise<void> {
let config: relationalStore.StoreConfig = {
// 数据库名称
name: DB_FILENAME,
// 数据库操作安全等级
securityLevel: relationalStore.SecurityLevel.S1
}
return new Promise<void>((resolve, reject) => {
// 获取关系型数据库操作对象
relationalStore.getRdbStore(context, config)
.then(rdbStore => {
this.rdbStore = rdbStore
// 记录日志
Logger.debug('rdbStore 初始化完成!')
resolve()
})
.catch(reason => {
Logger.debug('rdbStore 初始化异常', JSON.stringify(reason))
reject(reason)
})
})
}
// 创建表函数,传入创建表语句
createTable(createSQL: string): Promise<void> {
return new Promise((resolve, reject) => {
this.rdbStore.executeSql(createSQL)
.then(() => {
Logger.debug('创建表成功', createSQL)
resolve()
})
.catch(err => {
Logger.error('创建表失败,' + err.message, JSON.stringify(err))
reject(err)
})
})
}
// 建立insert方法的映射关系(实体数据插入到数据库的字段映射)
buildValueBucket(obj: any, columns: ColumnInfo[]): relationalStore.ValuesBucket {
let value = {}
columns.forEach(info => {
let val = obj[info.name]
if (typeof val !== 'undefined') {
value[info.columnName] = val
}
})
return value
}
// 新增方法,参数为表名称和新增对象
insert(tableName: string, obj: any, columns: ColumnInfo[]): Promise<number> {
return new Promise((resolve, reject) => {
// 1.构建新增数据
let value = this.buildValueBucket(obj, columns)
// 2.新增
this.rdbStore.insert(tableName, value, (err, id) => {
if (err) {
Logger.error('新增失败!', JSON.stringify(err))
reject(err)
} else {
Logger.debug('新增成功!新增id:', id.toString())
resolve(id)
}
})
})
}
// 删除方法,传入删除条件
delete(predicates: relationalStore.RdbPredicates): Promise<number> {
return new Promise((resolve, reject) => {
this.rdbStore.delete(predicates, (err, rows) => {
if (err) {
Logger.error('删除失败!', JSON.stringify(err))
reject(err)
} else {
Logger.debug('删除成功!删除行数:', rows.toString())
resolve(rows)
}
})
})
}
// 查询方法,传入查询条件,字段,返回结果
queryForList<T>(predicates: relationalStore.RdbPredicates, columns: ColumnInfo[]): Promise<T[]> {
return new Promise((resolve, reject) => {
this.rdbStore.query(predicates, columns.map(info => info.columnName), (err, result) => {
if (err) {
Logger.error('查询失败!', JSON.stringify(err))
reject(err)
} else {
Logger.debug('查询成功!查询行数:', result.rowCount.toString())
resolve(this.parseResultSet(result, columns))
}
})
})
}
// 解析结果集
parseResultSet<T> (result: relationalStore.ResultSet, columns: ColumnInfo[]): T[] {
// 1.声明最终返回的结果
let arr = []
// 2.判断是否有结果
if (result.rowCount <= 0) {
return arr
}
// 3.处理结果
while (!result.isAtLastRow) {
// 3.1.去下一行
result.goToNextRow()
// 3.2.解析这行数据,转为对象
let obj = {}
columns.forEach(info => {
let val = null
switch (info.type) {
case ColumnType.LONG:
val = result.getLong(result.getColumnIndex(info.columnName))
break
case ColumnType.DOUBLE:
val = result.getDouble(result.getColumnIndex(info.columnName))
break
case ColumnType.STRING:
val = result.getString(result.getColumnIndex(info.columnName))
break
case ColumnType.BLOB:
val = result.getBlob(result.getColumnIndex(info.columnName))
break
}
obj[info.name] = val
})
// 3.3.将对象填入结果数组
arr.push(obj)
Logger.debug('查询到数据:', JSON.stringify(obj))
}
return arr
}
}
let dbUtil: DbUtil = new DbUtil();
export default dbUtil as DbUtil
ColumnInfo.ts
export interface ColumnInfo{
// 实体字段
name: string
// 映射到数据库对应的字段
columnName: string
// 数据库字段类型
type: ColumnType
}
export enum ColumnType{
LONG,
DOUBLE,
STRING,
BLOB
}
Logger.ts
import hilog from '@ohos.hilog';
const LOGGER_PREFIX: string = 'OliannaWen.db';
class Logger {
private domain: number;
private prefix: string;
// format Indicates the log format string.
private format: string = '%{public}s, %{public}s';
/**
* constructor.
*
* @param prefix Identifies the log tag.
* @param domain Indicates the service domain, which is a hexadecimal integer ranging from 0x0 to 0xFFFFF
* @param args Indicates the log parameters.
*/
constructor(prefix: string = '', domain: number = 0xFF00) {
this.prefix = prefix;
this.domain = domain;
}
debug(...args: string[]): void {
hilog.debug(this.domain, this.prefix, this.format, args);
}
info(...args: string[]): void {
hilog.info(this.domain, this.prefix, this.format, args);
}
warn(...args: string[]): void {
hilog.warn(this.domain, this.prefix, this.format, args);
}
error(...args: string[]): void {
hilog.error(this.domain, this.prefix, this.format, args);
}
}
export default new Logger(LOGGER_PREFIX, 0xFF02);
更多推荐
所有评论(0)