ToB企服应用市场:ToB评测及商务社交产业平台
标题:
基于鸿蒙OS4的关系数据库使用学习——以浅易版备忘录为例
[打印本页]
作者:
三尺非寒
时间:
2024-6-11 11:30
标题:
基于鸿蒙OS4的关系数据库使用学习——以浅易版备忘录为例
概述
这里是我的项目地址,欢迎大家下载参考~有问题欢迎相互指出,谢谢!!
项目gitee地址
丑化说在前头,这个备忘录真的是十分大略,这一篇的写作目的不是为了能告诉读者备忘录怎么写和怎么美化,而是希望在现有鸿蒙OS4关系型数据库教学还比较少的情况下,官网教学也比较大略,把复杂的数据库设置抽离出来,让大家少走点弯路,让大家能更快的使用关系型数据库实现自己想要的业务目标。
笔者走了许多弯路了呜呜,希望大家多多点赞收藏~~
废话不多说,开干!!
这个学习案例,主要是参考b站大佬的备忘录设计和华为开辟者官网的例子记账本,大家也可以在了解根本关系型数据库怎么设置后详细学习
我们主要/scr/main的目录布局如下:
../scr/main目录下文件树结构展示
.
|-- constants
| `-- CommonConstants.ets
|-- database
| |-- MemoTable.ets
| `-- Rdb.ets
|-- ets
| |-- component
| | `-- MemoItem.ets
| |-- entryability
| | `-- EntryAbility.ts
| `-- pages
| `-- Index.ets
|-- model
| |-- MemoModel.ets
| `-- TableInterface.ets
|-- module.json5
|-- resources
| |-- base
| | |-- element
| | | |-- color.json
| | | `-- string.json
| | |-- media
| | | `-- icon.png
| | `-- profile
| | `-- main_pages.json
| |-- en_US
| | `-- element
| | `-- string.json
| |-- rawfile
| `-- zh_CN
| `-- element
| `-- string.json
`-- utils
`-- Logger.ets
复制代码
数据库的设置
我们先设置数据库
在./main/constants目录下,创建CommonConstants.ets文件,在这个文件里,我们存放Rdb数据库的根本设置,详细跟官网样例也差不多
import relationalStore from '@ohos.data.relationalStore'
import { MemoTable } from '../model/TableInterface'
export default class CommonConstants {
// Rdb 数据库配置
static readonly STORE_CONFIG:relationalStore.StoreConfig = {
name:'database.db',
securityLevel:relationalStore.SecurityLevel.S1
}
static readonly MEMO_TABLE:MemoTable = {
tableName:'memoTable',
sqlCreate:'CREATE TABLE IF NOT EXISTS memoTable(id INTEGER PRIMARY KEY AUTOINCREMENT, updateTime INTEGER, content TEXT)',
columns:['id','updateTime','content']
}
// 一些日志控制参数
static readonly RDB_TAG = '[Debug.Rdb]';
static readonly TABLE_TAG = '[Debug.memoTable]';
static readonly INDEX_TAG = '[Debug.Index]';
}
复制代码
我在学习的时间注意到,大佬在/main/model目录下,设置了TableInterface.ets文件,存放了一个MeMoTable接口
这种接口的设置,不用设置关键词function,我认识到大概一个是为了给CommonConstants类中的MEMO_TABLE内部元素设置类型,一个是降低代码耦合度便于后面维护
在/main/model目录下,新建TableInterface.ets文件,写一个MeMoTable接口
```typescript
export interface MemoTable {
tableName: string
sqlCreate: string
columns: string[]
}
复制代码
原来的界说如下
interface 接口名{
接口代码:一般定义规则、方法等
方法名(形参:形参类型):方法返回值
}
复制代码
进一步,大佬对数据库的操作进行了一层
抽象
,这个抽象的意思就是把很复杂的操作用几个函数给你概括起来了
就像我们假如形容一辆车,我们原来按照比较机器的方法,要界说外壳轮廓、动力参数什么的,现在直接告诉你小轿车、发动机V8什么的,你就大概了解了,我想后者就是抽象,把复杂的东西简朴化
在/main/database目录下,新建Rdb.ets文件,这个文件就是负责抽象复杂的数据库操作方法,不用来实现详细业务,只规定获取rdbStore对象,并用哪张表增删改查之类的流程
我们后续要使用数据库的数据操作时,数据操作也被简化为getRdbStore, insertData, deleteData, updateData, query方法
import relationalStore from '@ohos.data.relationalStore';
import CommonConstants from '../constants/CommonConstants';
import Logger from '../utils/Logger';
// 抽象的Rdb类,没有业务属性,可以基于这个类创建带有业务属性的一张或多张表
export default class Rdb {
// 管理关系数据库(RDB)方法属性 类型是RdbStore 或 null
private rdbStore: relationalStore.RdbStore | null = null;
// 数据库表名称
private tableName: string;
// 创建SQLite表的语句字符串
private sqlCreateTable: string;
// 列名字段的数组
private columns: Array<string>;
// 实例化 Rdb 对象时,初始化表名、创建表的语句、列名字段的数组
constructor(tableName: string, sqlCreateTable: string, columns: Array<string>) {
this.tableName = tableName;
this.sqlCreateTable = sqlCreateTable;
this.columns = columns;
}
// 获取操作数据库RdbStore对象的方法,接收一个回调函数
getRdbStore(callback: Function = () => {
}) {
// 如果 回调函数为空、或undefined 打印错误日志,退出方法
if (!callback || typeof callback === 'undefined' || callback === undefined) {
Logger.info(CommonConstants.RDB_TAG, 'getRdbStore() has no callback!');
return;
}
// 如果属性rdbStore 不为空,说明操作对象已经初始化,打印日志,执行回调函数,退出方法
if (this.rdbStore !== null) {
Logger.info(CommonConstants.RDB_TAG, 'The rdbStore exists.');
callback();
return
}
// 执行到此处,说明回调函数不为空,且rdbStore尚未初始化
// 获取上下文
let context: Context = getContext(this) as Context;
/*
获取RdbStore接口的方法,接收三个参数
context :应用上下文
config :数据库配置
callback :回调函数,异步返回rdb对象
*/
relationalStore.getRdbStore(context, CommonConstants.STORE_CONFIG, (err, rdb) => {
// 如果发生错误,打印日志,退出方法
if (err) {
Logger.error(CommonConstants.RDB_TAG, `gerRdbStore() failed, err: ${err}`);
return;
}
// 如果没有错误,为rdbStore属性赋值为rdb
this.rdbStore = rdb;
// 执行Sql语句,使用创建表的字符串
this.rdbStore.executeSql(this.sqlCreateTable);
// 打印日志
Logger.info(CommonConstants.RDB_TAG, 'getRdbStore() finished.');
// 执行方法入参的回调函数
callback();
});
}
// 插入数据的方法,入参为表格的存储键值对,和回调函数
insertData(data: relationalStore.ValuesBucket, callback: Function = () => {
}) {
// 如果回调函数为空、或undefined 打印错误日志,退出方法
if (!callback || typeof callback === 'undefined' || callback === undefined) {
Logger.info(CommonConstants.RDB_TAG, 'insertData() has no callback!');
return;
}
// 创建结果标识局部变量,默认为false
let resFlag: boolean = false;
// 创建存储键值对局部变量,默认为入参data
const valueBucket: relationalStore.ValuesBucket = data;
// 如果rdbStore存在则执行
if (this.rdbStore) {
// 执行rdbStore的插入数据方法,入参为表名、存储键值对、异步回调函数
this.rdbStore.insert(this.tableName, valueBucket, (err, ret) => {
if (err) {
// 如果发生错误,打印日志,执行入参的回调函数,并传入结果标识 false
Logger.error(CommonConstants.RDB_TAG, `insertData() failed, err: ${err}`);
callback(resFlag);
return;
}
// 如果操作成功,打印日志,执行回调函数,并传入返回ret(行ID)
Logger.info(CommonConstants.RDB_TAG, `insertData() finished: ${ret}`);
callback(ret);
});
}
}
// 删除数据的方法,接收谓词和回调函数两个参数
deleteData(predicates: relationalStore.RdbPredicates, callback: Function = () => {
}) {
// 如果回调函数为空、或undefined 打印错误日志,退出方法
if (!callback || typeof callback === 'undefined' || callback === undefined) {
Logger.info(CommonConstants.RDB_TAG, 'deleteData() has no callback!');
return;
}
// 创建结果标识局部变量,默认为false
let resFlag: boolean = false;
// 如果rdbStore存在则执行
if (this.rdbStore) {
// rdbStore的删除方法,入参为谓词、异步回调函数
this.rdbStore.delete(predicates, (err, ret) => {
// 如果发生错误,打印日志,执行入参的回调函数,并传入结果标识 false
if (err) {
Logger.error(CommonConstants.RDB_TAG, `deleteData() failed, err: ${err}`);
callback(resFlag);
return;
}
// 如果删除成功,打印日志,执行回调函数,并传入返回ret(行ID)
Logger.info(CommonConstants.RDB_TAG, `deleteData() finished: ${ret}`);
callback(!resFlag);
});
}
}
// 更新数据的方法,接收三个参数:谓词、存储键值对、回调函数
updateData(predicates: relationalStore.RdbPredicates, data: relationalStore.ValuesBucket, callback: Function = () => {
}) {
// 如果回调函数为空、或undefined 打印错误日志,退出方法
if (!callback || typeof callback === 'undefined' || callback === undefined) {
Logger.info(CommonConstants.RDB_TAG, 'updateDate() has no callback!');
return;
}
// 创建结果标识局部变量,默认为false
let resFlag: boolean = false;
// 创建存储键值对局部变量,默认为入参data
const valueBucket: relationalStore.ValuesBucket = data;
// 如果rdbStore存在则执行
if (this.rdbStore) {
// rdbStore的更新方法,接收三个参数,存储键值对、谓词、回调函数
this.rdbStore.update(valueBucket, predicates, (err, ret) => {
if (err) {
// 如果发生错误,打印日志,执行入参的回调函数,并传入结果标识 false
Logger.error(CommonConstants.RDB_TAG, `updateData() failed, err: ${err}`);
callback(resFlag);
return;
}
// 如果更新成功,打印日志,执行回调函数,并传入返回成功的标识 true
Logger.info(CommonConstants.RDB_TAG, `updateData() finished: ${ret}`);
callback(!resFlag);
});
}
}
// 查询数据的方法,接收两个参数,谓词、回调函数
query(predicates: relationalStore.RdbPredicates, callback: Function = () => {
}) {
// 如果回调函数为空、或undefined 打印错误日志,退出方法
if (!callback || typeof callback === 'undefined' || callback === undefined) {
Logger.info(CommonConstants.RDB_TAG, 'query() has no callback!');
return;
}
// 如果rdbStore存在则执行
if (this.rdbStore) {
// rdbStore的查询方法,接收三个参数,谓词,数据库列名的数组,异步回调函数
this.rdbStore.query(predicates, this.columns, (err, resultSet) => {
// 如果发生错误,打印日志,退出方法
if (err) {
Logger.error(CommonConstants.RDB_TAG, `query() failed, err: ${err}`);
return;
}
// 如果没有错误,打印日志
Logger.info(CommonConstants.RDB_TAG, 'query() finished.');
// 执行入参的回调函数,传入查询结果
callback(resultSet);
// 关闭结果集
resultSet.close();
});
}
}
}
复制代码
数据实现
接下来我们来写详细的数据
我们在/main/model目录下创建MeMoModel.ets,设置数据类,设置类MeMoModel,这个类用来管理添加的备忘录的根本信息
class MemoModel {
id: number
updateTime: number
content: string
constructor(id: number, updateTime: number, content: string) {
this.id = id
this.updateTime = updateTime
this.content = content
}
}
export default MemoModel
复制代码
我们在/main/database目录下创建MemoTable.ets,这个是用来进行备忘录详细业务逻辑操作的
我们一开始先实例化Rdb类,然后依次获取getRdbStore,insertData,deleteData,updateData,query方法,我们在这里的方法里,可以详细设置我们业务数据怎么处理的,比如在query里,我们是根据须要组装变量tmp,并且加到result中
import relationalStore from '@ohos.data.relationalStore';
import MemoModel from '../model/MemoModel'
import CommonConstants from '../constants/CommonConstants';
import Rdb from './Rdb';
// 笔记的数据库类,基于Rdb类,有业务属性
export default class MemoTable {
// 通过Rdb类实例化memoTable对象,使用常量文件“CommonConstants”中配置的参数
private memoTable = new Rdb(CommonConstants.MEMO_TABLE.tableName, CommonConstants.MEMO_TABLE.sqlCreate,
CommonConstants.MEMO_TABLE.columns);
// 构造函数,执行getRdbStore方法
constructor(callback: Function = () => {
}) {
this.memoTable.getRdbStore(callback);
}
// 通过memoTable对象,执行原Rdb类中的getRdbStore方法,为memoTable对象获取rdbStore操作对象
getRdbStore(callback: Function = () => {
}) {
// 透传回调函数
this.memoTable.getRdbStore(callback);
}
// 插入数据的方法,接收单条memo笔记对象,和回调函数
insertData(memo: MemoModel, callback: Function) {
// 通过工具函数,将单条memo笔记,转化为存储健值对
const valueBucket: relationalStore.ValuesBucket = generateBucket(memo);
// 执行memoTable的插入数据方法,透传回调函数
this.memoTable.insertData(valueBucket, callback);
}
// 删除数据的方法,接收单条memo笔记对象,和回调函数
deleteData(memo: MemoModel, callback: Function) {
// 初始化操作数据库的谓词对象
let predicates = new relationalStore.RdbPredicates(CommonConstants.MEMO_TABLE.tableName);
// 配置谓词以匹配数据表的id列中值的字段,为笔记对象的id
predicates.equalTo('id', memo.id);
// 使用谓词执行memoTable的删除方法,透传回调函数
this.memoTable.deleteData(predicates, callback);
}
// 更新数据的方法,接收单条memo笔记对象,和回调函数
updateData(memo: MemoModel, callback: Function) {
// 通过工具函数,将单条memo笔记,转化为存储健值对
const valueBucket: relationalStore.ValuesBucket = generateBucket(memo);
// 初始化操作数据库的谓词对象
let predicates = new relationalStore.RdbPredicates(CommonConstants.MEMO_TABLE.tableName);
// 配置谓词以匹配数据表的id列中值的字段,为笔记对象的id
predicates.equalTo('id', memo.id);
// 使用谓词执行memoTable的更新方法,透传回调函数
this.memoTable.updateData(predicates, valueBucket, callback);
}
// 查询全部笔记的方法
query(callback: Function) {
// 初始化操作数据库的谓词对象
let predicates = new relationalStore.RdbPredicates(CommonConstants.MEMO_TABLE.tableName);
// 使用谓词执行memoTable的查询方法,此时谓词匹配未指定(equalTo),所以将查询全部
this.memoTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
// 创建局部变量,存储结果的行数
let count: number = resultSet.rowCount;
// 如果查询的结果为0,执行回调函数,传入空数组
if (count === 0 || typeof count === 'string') {
console.log(`${CommonConstants.TABLE_TAG}` + 'Query no results!');
callback([]);
} else {
// 如果有结果,将结果集指向第一行
resultSet.goToFirstRow();
// 创建局部变量,存储最后将返回的结果数组
const result: MemoModel[] = [];
// 使用循环为结果添加内容
for (let i = 0; i < count; i++) {
let tmp: MemoModel = {
id: 0, updateTime: 0, content: ''
};
tmp.id = resultSet.getDouble(resultSet.getColumnIndex('id'));
tmp.updateTime = resultSet.getDouble(resultSet.getColumnIndex('updateTime'));
tmp.content = resultSet.getString(resultSet.getColumnIndex('content'));
result[i] = tmp;
// 转至下一行
resultSet.goToNextRow();
}
// 执行回调函数,把所有的查询结果传入
callback(result);
}
});
}
}
// 工具函数,将memo笔记的数据结构,转化为存储键值对
function generateBucket(memo: MemoModel): relationalStore.ValuesBucket {
let obj: relationalStore.ValuesBucket = {};
obj.updateTime = memo.updateTime
obj.content = memo.content
return obj;
}
复制代码
页面设置
我们先在Index.ets目录下,设置一个简朴的页面,可以或许实现备忘录根本样式,并且能添加大略卡片样式的列表
@Entry
@Component
struct Index {
// 缓存的原始数组
originMemoList: MemoModel[] = []
// 页面中展示的memo列表
@State memoList: MemoModel[] = []
// 新建暂存内容
@State addContent: string = ''
@State number: number = 1
// 当前编辑的memo索引
editingMemoIndex: number = -1
build() {
Stack() {
// 主体页面
Column() {
Row() {
Text("MeMo")
.fontSize(20)
.fontColor(Color.White)
.margin({ left:20})
Blank()
Button() {
Text("我是按钮")
.fontSize(20)
.fontColor(Color.White)
}
.height(40)
.width(150)
.onClick(() => {
this.number = this.number + 1
})
}
.width('100%')
.height(60)
.linearGradient({
direction:GradientDirection.Bottom,
colors:[[Color.Black, 0.5], [Color.Gray, 1]]
})
.shadow({
radius:10
})
Divider()
.color('#604637')
// 笔记列表
Scroll() {
Column() {
Text(String(this.number))
.fontSize(40)
List({space: 10}) {
ForEach(this.memoList, (item: MemoModel, index) => {
ListItem() {
Row() {
Text(item.content)
Text(String(item.updateTime))
}
}.card()
})
}
}
}
}
.width('100%')
.height('100%')
}
}
}
复制代码
手机模仿器界面如下
注意看,我这里是不能用它自带的Previewer进行展示的,我的Previewer会呈空缺
我感觉很少人说过这个,网上超少,而且这个情况是我一旦使用了数据库之后,他立马就会变成空缺,只能用手机模仿器显示,我想大概Previewer不能涉及有数据相关的操作,而真机模仿就可以。
功能展示
功能很简朴,如下,并且应用关闭了之后,数据也不会丢失,会继续保存下来。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4