概述
这里是我的项目地址,欢迎大家下载参考~有问题欢迎相互指出,谢谢!!
项目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企服之家,中国第一个企服评测及商务社交产业平台。 |