HarmonyOS期末项目——作业清单(三)搭建关系型数据库

系列文章目录

HarmonyOS期末项目——作业清单(一)项目介绍和应用主页面设计
HarmonyOS期末项目——作业清单(二)任务创建与编辑
HarmonyOS期末项目——作业清单(四)通用工具类
HarmonyOS期末项目——作业清单(完结篇)组件与视图

目录

系列文章目录

HarmonyOS期末项目——作业清单(一)项目介绍和应用主页面设计

HarmonyOS期末项目——作业清单(二)任务创建与编辑

HarmonyOS期末项目——作业清单(四)通用工具类

HarmonyOS期末项目——作业清单(完结篇)组件与视图

前言

一、关键技术

二、交互示意图

三、创建数据库

3.1PreferenceDB.ets (偏好数据库)

3.1.1 功能

3.1.2 代码文件

3.2 TaskDB.ets (任务数据库)

3.2.1 功能简介

3.2.2 代码文件

四、数据表定义

4.1 CategoryTable.ets (类别表)

4.1.1 功能简介

4.1.2 代码文件

4.2 PreferenceData.ets (偏好数据类)

4.2.1功能简介

4.2.2 代码文件

4.3 TaskCategoryData.ets (任务类别数据类)

4.3.1 功能简介

4.3.2 代码文件

4.4 TaskListItemData.ets (任务列表项数据类)

4.4.1 功能简介

4.4.2 代码文件

五、创建数据表

5.1 功能简介

5.2 代码文件

六、数据库初始化

6.1 功能简介

6.2 代码文件

七、遇到的问题及解决方案

问题1:数据列类型不匹配

问题2:查询结果为空

总结


前言

在前面的两篇博文中,我已经详细介绍了作业清单项目的基本概况和应用主页面的设计,随后探讨了如何实现任务的创建与编辑功能。作业清单作为一个帮助学生和工作人员高效管理任务的工具,通过清晰简洁的界面设计和多样的功能支持,提高了用户的工作效率和时间管理能力。

本篇博文将继续深入项目的技术实现,重点介绍如何搭建关系型数据库,以支持作业清单应用的数据管理需求。我将详细讲解数据库的设计过程、表结构的定义、数据的增删改查操作,以及如何确保数据的一致性和完整性。通过这篇文章,读者将能够掌握在项目中有效运用关系型数据库的技巧,为后续的功能开发打下坚实的基础。


一、关键技术

数据模型和数据库管理
 

  • 数据模型(Bean):通过定义数据模型类(如DDLDetailClass、PreferenceData、TaskCategoryData、TaskListItemData),结构化地管理和存储应用数据。
  • 数据库(Database):使用HarmonyOS的数据存储方案,创建和管理数据库表(如CategoryTable、PreferenceDB、TaskDB、TaskTable),实现数据的增删改查操作。

二、交互示意图

三、创建数据库

3.1PreferenceDB.ets (偏好数据库)

管理用户偏好设置的数据库操作。

3.1.1 功能

  • 获取偏好设置存储对象:getPreferenceStorage() 方法用于获取偏好设置存储对象。该对象是通过 dataPreferences.getPreferences(context, 'Pref.db') 获取的。如果获取失败,将会记录错误信息到日志中。
  • 设置偏好设置:putPreference(key: string, value: string) 方法用于向偏好设置中存储键值对。它会将给定的键值对存储到偏好设置中,并通过 preference.flush() 立即将更改刷新到存储中。如果存储操作失败,将会记录错误信息到日志中。
  • 获取偏好设置:getPreference(key: string): Promise<string> 方法用于根据键获取对应的偏好设置值。它会首先检查是否已经获取了偏好设置存储对象,如果没有则会先获取。然后尝试从偏好设置中获取指定键的值,并返回获取的值。如果获取失败,将会记录错误信息到日志中。

3.1.2 代码文件



let context = getContext(this)
let preference: dataPreferences.Preferences
let preferenceTemp: dataPreferences.Preferences

class PreferenceDB {
  async getPreferenceStorage() {
    try {
      preference = await dataPreferences.getPreferences(context, 'Pref.db')
    } catch(err){
      Logger.error(`PrefDB: failed to get storage: ${err}`)
    }
  }
  async putPreference(key: string, value: string) {
    try {
      await preference.put(key, value)
    } catch(err) {
      Logger.error(`PrefDB: failed to put pref: ${err}`)
    }
    await preference.flush()
  }
  async getPreference(key: string): Promise<string> {
    let res: string = ''
    if (!preference) preference = await dataPreferences.getPreferences(context, 'Pref.db')
    try {
      res = (await preference.get(key, '')).toString()
    } catch(err) {
      Logger.error(`PrefDB: failed to get pref: ${err}`)
    }
    return res
  }
}

export default new PreferenceDB()

3.2 TaskDB.ets (任务数据库)

管理任务的数据库操作。

3.2.1 功能简介

  • TaskDB 类用于执行与任务相关的数据库操作,包括插入、删除、更新和查询数据等功能。
  • 通过 getRdbStore 方法获取数据库存储实例,确保数据库操作的准备就绪。
  • 提供了 insertData 方法,用于向数据库中插入数据,支持传入数据对象和回调函数。
  • deleteData 方法用于删除数据库中的数据,可以传入条件谓词以指定删除条件。
  • updateData 方法用于更新数据库中的数据,支持传入更新数据和条件谓词。
  • query 方法用于执行查询操作,支持传入条件谓词以指定查询条件,并通过回调函数返回查询结果。
  • 类构造函数接受表名、创建表的 SQL 语句、表的列信息和数据库配置参数作为参数,确保了 TaskDB 实例与指定的数据库表进行交互。
  • 通过日志记录器 Logger 对数据库操作过程进行日志记录,方便调试和错误追踪。

3.2.2 代码文件



export default class TaskDB {
  private rdbStore: relationalStore.RdbStore | null = null
  private tableName: string
  private sqlCreateTable: string
  private columns: Array<string>
  private RDB_TAG: string = '[DEBUG_RDB]'
  private StoreConfig: relationalStore.StoreConfig


  constructor(tableName: string, sqlCreateTable: string, columns: Array<string>, Config: relationalStore.StoreConfig = CommonConstants.STORE_CONFIG) {
    this.tableName = tableName
    this.sqlCreateTable = sqlCreateTable
    this.columns = columns
    this.StoreConfig = Config
  }

  getRdbStore(callback: Function = () => {}) {
    if (!callback || typeof callback === 'undefined' || callback === undefined) {
      Logger.info(this.RDB_TAG, 'getRdbStore() has no callback!');
      return;
    }
    if (this.rdbStore !== null) {
      callback();
      return;
    }
    let context: Context = getContext(this) as Context
    relationalStore.getRdbStore(context, this.StoreConfig, (err, rdb) => {
      if (err) {
        Logger.error(this.RDB_TAG, `gerRdbStore() failed, err: ${err}`);
        return;
      }
      this.rdbStore = rdb
      this.rdbStore.executeSql(this.sqlCreateTable)
      // 假定这里 execute 之后不会出事
      callback();
    })
  }

  updateColumns(newColumn: string, newColumnData: string) {
    this.rdbStore.executeSql(`ALTER TABLE ${this.tableName} ADD COLUMN ${newColumn} ${newColumnData}`)
  }


  insertData(data: relationalStore.ValuesBucket, callback: Function = () => {}) {
    if (!callback || typeof callback === 'undefined' || callback === undefined) {
      Logger.info(this.RDB_TAG, 'insertData() has no callback!');
      return;
    }
    const valueBucket: relationalStore.ValuesBucket = data
    if (this.rdbStore) {
      Logger.debug(this.RDB_TAG, this.tableName)
      this.rdbStore.insert(this.tableName, valueBucket, (err, ret) => {
        if (err) {
          Logger.error(this.RDB_TAG, `insertData() failed, err: ${err.code}, ${err.name}, ${err.message}, valueB = ${JSON.stringify(valueBucket)}, ret = ${ret}`);
          callback(false)
          return
        }
        Logger.debug(this.RDB_TAG, `insert finished: ${ret}`)
        callback(ret)
      })
    }
  }
  deleteData(predicates:  relationalStore.RdbPredicates, callback: Function = () => {}) {
    if (!callback || typeof callback === 'undefined' || callback === undefined) {
      Logger.info(this.RDB_TAG, 'deleteData() has no callback!');
      return;
    }
    if (this.rdbStore) {
      this.rdbStore.delete(predicates, (err, ret) => {
        if (err) {
          Logger.error(this.RDB_TAG, `deleteData() failed, err: ${err}`);
          callback(false);
          return;
        }
        Logger.info(this.RDB_TAG, `deleteData() finished: ${ret}`);
        callback(true);
      })
    }
  }
  updateData(predicates: relationalStore.RdbPredicates, data: relationalStore.ValuesBucket, callback: Function = () => {}) {
    if (!callback || typeof callback === 'undefined' || callback === undefined) {
      Logger.info(this.RDB_TAG, 'updateDate() has no callback!');
      return;
    }
    const valueBucket: relationalStore.ValuesBucket = data
    if (this.rdbStore) {
      this.rdbStore.update(valueBucket, predicates, (err, ret) => {
        if (err) {
          Logger.error(this.RDB_TAG, `updateData() failed, err: ${err}`);
          callback(false);
          return;
        }
        Logger.info(this.RDB_TAG, `updateData() finished: ${ret}`);
        callback(true);
      })
    }
  }
  query(predicates: relationalStore.RdbPredicates, callback: Function = () => {}) {
    if (!callback || typeof callback === 'undefined' || callback === undefined) {
      Logger.info(this.RDB_TAG, 'queryTaskName() has no callback!');
      return;
    }
    if (this.rdbStore) {
      this.rdbStore.query(predicates).then((resultSet) => {
        Logger.debug(this.RDB_TAG, `query finished.`)
        callback(resultSet)
        resultSet.close()
      }).catch((err) => {
        if (err) {
          Logger.error(this.RDB_TAG, `query() failed, err:  ${err}`);
          return;
        }
      })
    }
  }

}

四、数据表定义

定义数据表的结构和字段。

4.1 CategoryTable.ets (类别表)

定义了任务类别的数据库表结构和操作。

4.1.1 功能简介

  • CategoryTable 类用于对任务类别数据进行数据库操作,包括插入、删除、更新和查询数据等功能。
  • 通过构造函数初始化 TaskDB 实例,确保CategoryTable 与指定的数据库表进行交互。
  • 提供了 insertData 方法,用于向数据库中插入任务类别数据,支持传入任务类别对象和回调函数。
  • deleteData 方法用于根据任务类别对象删除数据库中的数据。
  • updateData 方法用于根据任务类别对象更新数据库中的数据。
  • query 方法用于执行查询操作,支持根据任务类别的不同属性进行查询,并通过回调函数返回查询结果。
  • 提供了基础查询方法 basic_query,用于处理查询操作的基础逻辑,支持查询所有任务类别或根据特定属性进行条件查询。
  • 通过日志记录器 Logger 对数据库操作过程进行日志记录,方便调试和错误追踪。
  • 提供了 generateBucket 方法,用于生成 relationalStore.ValuesBucket 对象,方便进行数据操作。

4.1.2 代码文件


export default class CategoryTable {
  private cateTable = new TaskDB(CommonConstants.CATEGORY_TABLE_INIT.tableName, CommonConstants.CATEGORY_TABLE_INIT.sqlCreate,
    CommonConstants.CATEGORY_TABLE_INIT.columns, CommonConstants.CATEGORY_STORE_CONFIG)

  constructor(callback: Function = () => {}) {
    this.cateTable.getRdbStore(callback);
  }

  getRdbStore(callback: Function = () => {}) {
    this.cateTable.getRdbStore(callback)
  }

  insertData(prefData: TaskCategoryData, callback: Function) {
    const valueBucket: relationalStore.ValuesBucket = generateBucket(prefData)
    this.cateTable.insertData(valueBucket, callback)
  }

  deleteData(prefData: TaskCategoryData, callback: Function) {
    let predicates = new relationalStore.RdbPredicates(CommonConstants.CATEGORY_TABLE_INIT.tableName)
    predicates.equalTo('id', prefData.id)
    this.cateTable.deleteData(predicates, callback)
  }

  updateData(prefData: TaskCategoryData, callback: Function) {
    const valueBucket: relationalStore.ValuesBucket = generateBucket(prefData)
    let predicates = new relationalStore.RdbPredicates(CommonConstants.CATEGORY_TABLE_INIT.tableName)
    predicates.equalTo('id', prefData.id)
    this.cateTable.updateData(predicates, valueBucket, callback)
  }

  query(queryID: number, callback: Function){
    let tmp = new TaskCategoryData(); tmp.id = queryID;
    this.basic_query('id', tmp, callback, (queryID == 0))
  }
  private basic_query(query_type: string, queryData: TaskCategoryData, callback: Function, isAll: boolean = true) {
    Logger.debug(`TaskTable query_type: ${query_type}, query_data: ${JSON.stringify(queryData)}, visit: ${queryData[query_type]}`)
    let predicates = new relationalStore.RdbPredicates(CommonConstants.CATEGORY_TABLE_INIT.tableName)
    if (!isAll) predicates.like(query_type, queryData[query_type])
    this.cateTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
      let count: number = resultSet.rowCount
      Logger.debug(`Category Table number: ${count}`)
      if (count === 0 || typeof count === 'string') {
        // empty
        callback([])
      } else {
        resultSet.goToFirstRow()
        // get results
        const result: TaskCategoryData[] = []
        for (let i = 0; i < count; ++i) {
          let tmp: TaskCategoryData = new TaskCategoryData()
          for (let t = 0; t < CommonConstants.CATEGORY_TABLE_INIT.columns.length; ++t) {
            let nowColumn = CommonConstants.CATEGORY_TABLE_INIT.columns[t]
            let nowIndex = resultSet.getColumnIndex(nowColumn)

            switch (nowColumn) {
              case 'id':
                tmp[nowColumn] = resultSet.getDouble(nowIndex)
                break
              case 'name':
                tmp[nowColumn] = resultSet.getString(nowIndex)
                break
              case 'color':
                tmp[nowColumn] = resultSet.getString(nowIndex)
            }

            Logger.debug(`CateTable READING: nowC = ${nowColumn}, data = ${tmp[nowColumn]}`)
          }
          result[i] = tmp
          Logger.debug(`CateTable Reading DATA: ${JSON.stringify(tmp)}`)
          resultSet.goToNextRow()
        }
        callback(result)
      }
    })
  }
}

function generateBucket(data: TaskCategoryData): relationalStore.ValuesBucket {
  let obj: relationalStore.ValuesBucket = {}
  CommonConstants.CATEGORY_TABLE_INIT.columns.forEach((value) => {
    if (value == 'id') return;
    obj[value] = data[value];
  })
  return obj
}

4.2 PreferenceData.ets (偏好数据类)

管理用户的偏好设置。

4.2.1功能简介

  • PreferenceData 类实现了 PreferenceInterface 接口,用于表示用户偏好设置的数据对象。
  • 通过实现 PreferenceInterface 接口,确保了PreferenceData 类包含了必要的属性,使其符合用户偏好设置的数据结构要求。

4.2.2 代码文件


export interface PreferenceInterface {
  id: number
}
export default class PreferenceData implements PreferenceInterface {
  id: number = 1
}

4.3 TaskCategoryData.ets (任务类别数据类)

定义了任务类别的结构。


4.3.1 功能简介

  • 包含 color、name 和 id 属性,分别表示任务类别的颜色、名称和唯一标识符。
  • 通过实现 TaskCategoryDataInterface 接口,确保了 TaskCategoryData 类包含了必要的属性,使其符合任务类别的数据结构要求。

4.3.2 代码文件

export interface TaskCategoryDataInterface {
  color: string
  name: string
  id: number
}

export default class TaskCategoryData implements TaskCategoryDataInterface {
  color: string = '#000000'
  name: string = '默认清单'
  id: number = 0
}

4.4 TaskListItemData.ets (任务列表项数据类)

定义了任务列表项的结构。


4.4.1 功能简介

  • TaskListItemData 类实现了 ItemDataInterface 接口,用于表示任务列表项的数据对象。
  • 属性 ddl_state 包含了任务的DDL状态的阈值,根据任务的剩余时间与总时间的比例确定任务状态。
  • setAll 方法用于根据传入的任务类别列表更新任务项的DDL状态和类别名称。
  • setCategoryName 方法根据传入的任务类别列表设置任务项的类别名称。
  • getDDLState 方法根据任务的剩余时间与总时间的比例,以及DDL状态的阈值,确定任务的DDL状态。
  • getDDLPer 方法计算任务剩余时间与总时间的比例,用于展示任务完成百分比。
  • 通过实现 ItemDataInterface 接口,确保了 TaskListItemData 类包含了必要的属性,使其符合任务列表项的数据结构要求。

4.4.2 代码文件



export interface ItemDataInterface {
  id: number
  detail: string
  task_name: string
  start_date_stamp: number
  due_date_stamp: number
  is_completed: boolean
  ddl_detail: string
  category: number
  topped: boolean
}

@Observed
export class TaskListItemData implements ItemDataInterface {
  id: number = -1
  start_date_stamp: number = 0
  due_date_stamp: number = 0
  detail: string = ''
  subject: number = 0
  task_name: string = ''
  is_completed: boolean = false
  ddl_detail: string = '0.3-0.5-0.8'
  ddl_state = {
    critical: 0.3,
    hard: 0.5,
    medium: 0.8
  }
  category: number = 1
  categoryName: string = ''
  topped: boolean = false

  setAll(categoryList: TaskCategoryData[]) {
    let ddl_arr = this.ddl_detail.split('-')
    Logger.debug(`TaskDDL Info: arr = ${JSON.stringify(ddl_arr)}, det = ${this.ddl_detail}`)
    this.ddl_state.critical = Number(ddl_arr[0])
    this.ddl_state.hard = Number(ddl_arr[1])
    this.ddl_state.medium = Number(ddl_arr[2])
    this.setCategoryName(categoryList)
  }
  setCategoryName(categoryList: TaskCategoryData[]) {
    for (let i = 0; i < categoryList.length; ++i) {
      if (categoryList[i].id == this.category) {
        this.categoryName = categoryList[i].name
        break;
      }
    }
  }
  getDDLState(): string {
    let taskFullTime = this.due_date_stamp - this.start_date_stamp
    let nowTime = new Date()
    let remainingTime = this.due_date_stamp - nowTime.getTime()
    let resultPercentage = remainingTime / taskFullTime
    Logger.debug(`TaskDDL State: full = ${taskFullTime}, remaining = ${remainingTime}, per = ${resultPercentage}`)
    Logger.debug(`TaskDDL ------ due: ${new Date(this.due_date_stamp).toString()}, now: ${new Date().toString()}, start: ${new Date(this.start_date_stamp).toString()}`)
    Logger.debug(`TaskDDL ------: arr = ${JSON.stringify(this.ddl_state)}`)

    if (remainingTime < 0) return 'critical'
    if (resultPercentage < this.ddl_state.critical) return 'critical'
    else if (resultPercentage < this.ddl_state.hard) return 'hard'
    else if (resultPercentage < this.ddl_state.medium) return 'medium'
    else return 'easy'
  }
  getDDLPer(): number {
    let taskFullTime = this.due_date_stamp - this.start_date_stamp
    let nowTime = new Date()
    let remainingTime = this.due_date_stamp - nowTime.getTime()
    if (remainingTime <= 0) return 0
    let resultPercentage = remainingTime / taskFullTime
    return resultPercentage * 100
  }
}

五、创建数据表

通过SQL语句在数据库中创建所需的数据表。

TaskTable.ets

5.1 功能简介

  • TaskTable 类用于将任务数据转换为数据库中的存储形式,并提供了从数据库中检索任务数据的功能。
  • 通过实例化 TaskDB 类实现对任务数据表的操作,包括插入、删除、更新和查询等。
  • 构造函数初始化了 TaskDB 实例,获取了数据库存储。
  • updateColumns 方法用于更新任务数据表的列信息。
  • insertData 方法用于向任务数据表中插入新的任务数据。
  • deleteData 方法用于从任务数据表中删除指定的任务数据。
  • updateData 方法用于更新任务数据表中指定任务数据的信息。
  • queryTaskName 方法用于根据任务名称查询任务数据。
  • basic_query 方法是一个通用的查询方法,支持根据不同的查询类型和查询数据进行查询,从数据库中检索符合条件的任务数据,并将结果返回给回调函数。
  • generateBucket 方法用于生成 relationalStore.ValuesBucket 对象,将任务数据转换为数据库存储所需的格式。

5.2 代码文件


export default class TaskTable {
  private taskTable = new TaskDB(CommonConstants.TASK_TABLE_INIT.tableName, CommonConstants.TASK_TABLE_INIT.sqlCreate,
    CommonConstants.TASK_TABLE_INIT.columns)

  constructor(callback: Function = () => {}) {
    this.taskTable.getRdbStore(callback);
  }

  // test() { this.cateTable.test() }
  getRdbStore(callback: Function = () => {}) {
    this.taskTable.getRdbStore(callback)
  }

  updateColumns(newColumn: string, newColumnType: string) {
    let newColumnData: string = ''
    switch (newColumnType) {
      case 'double':
        newColumnData = 'INTEGER'
        break;
      case 'string':
        newColumnData = 'TEXT'
        break;
      case 'boolean':
        newColumnData = 'BOOLEAN'
      default:
        newColumnData = 'INTEGER'
    }
    Logger.debug(`UpdateColumns: ${newColumn} ${newColumnData}`)
    this.taskTable.updateColumns(newColumn, newColumnData)
  }

  insertData(taskData: TaskListItemData, callback: Function) {
    const valueBucket: relationalStore.ValuesBucket = generateBucket(taskData)
    this.taskTable.insertData(valueBucket, callback)
  }

  deleteData(taskData: TaskListItemData, callback: Function) {
    let predicates = new relationalStore.RdbPredicates(CommonConstants.TASK_TABLE_INIT.tableName)
    predicates.equalTo('id', taskData.id)
    this.taskTable.deleteData(predicates, callback)
  }

  updateData(taskData: TaskListItemData, callback: Function) {
    const valueBucket: relationalStore.ValuesBucket = generateBucket(taskData)
    let predicates = new relationalStore.RdbPredicates(CommonConstants.TASK_TABLE_INIT.tableName)
    predicates.equalTo('id', taskData.id)
    this.taskTable.updateData(predicates, valueBucket, callback)
  }
 
  queryTaskName(task_name: string, callback: Function, isAll: boolean = true) {
    let submit: TaskListItemData = new TaskListItemData(); submit.task_name = task_name
    this.basic_query("task_name", submit, callback, isAll)
    
  }
 
  basic_query(query_type: string, queryData: TaskListItemData, callback: Function, isAll: boolean = true) {
    Logger.debug(`TaskTable query_type: ${query_type}, query_data: ${JSON.stringify(queryData)}, visit: ${queryData[query_type]}`)
    let predicates = new relationalStore.RdbPredicates(CommonConstants.TASK_TABLE_INIT.tableName)
    if (!isAll) {
      if (CommonConstants.COLUMN_TYPE[query_type] == 'string') predicates.like(query_type, queryData[query_type])
      else predicates.equalTo(query_type, queryData[query_type])
    }
    this.taskTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
      let count: number = resultSet.rowCount
      Logger.debug(`TaskTable number: ${count}`)
      if (count === 0 || typeof count === 'string') {
        
        callback([])
      } else {
        resultSet.goToFirstRow()
        
        const result: TaskListItemData[] = []
        for (let i = 0; i < count; ++i) {
          let tmp: TaskListItemData = new TaskListItemData()
          for (let t = 0; t < CommonConstants.TASK_TABLE_INIT.columns.length; ++t) {
            let nowColumn = CommonConstants.TASK_TABLE_INIT.columns[t]
            let nowIndex = resultSet.getColumnIndex(nowColumn)

            switch (CommonConstants.COLUMN_TYPE[nowColumn]) {
              case 'double':
                tmp[nowColumn] = resultSet.getDouble(nowIndex)
                break
              case 'string':
                tmp[nowColumn] = resultSet.getString(nowIndex)
                break
              case 'boolean':
                tmp[nowColumn] = Boolean(resultSet.getDouble(nowIndex))
            }

            Logger.debug(`TaskTable READING: nowC = ${nowColumn}, data = ${tmp[nowColumn]}`)
          }
          result[i] = tmp
          Logger.debug(`TaskTable Reading DATA: ${JSON.stringify(tmp)}`)
          resultSet.goToNextRow()
        }
        callback(result)
      }
    })
  }
}

function generateBucket(taskData: TaskListItemData): relationalStore.ValuesBucket {
  let obj: relationalStore.ValuesBucket = {}
  for (let i = 1; i < CommonConstants.TASK_TABLE_INIT.columns.length; ++i) {
    let nowCol = CommonConstants.TASK_TABLE_INIT.columns[i]
    obj[nowCol] = taskData[nowCol]
  }
  return obj
}

六、数据库初始化

DDLDetailClass.ets
类 DDLDetailClass 提供了一个简单的数据结构,用于存储任务DDL(Deadline)的提示和详细信息。

6.1 功能简介

  • hint 属性存储了DDL的提示信息,例如“临近DDL”、“已过期”等。
  • detail 属性存储了DDL的详细信息,例如DDL的具体日期和时间等。
  • 构造函数接受两个参数,分别为 hint 和 detail,并将它们分别赋值给对象的对应属性。
     

6.2 代码文件

export default class DDLDetailClass {
  hint: string
  detail: string

  constructor(hint: string, detail: string) {
    this.hint = hint
    this.detail = detail
  }
}

七、遇到的问题及解决方案

问题1:数据列类型不匹配


描述:在调用 `updateColumns` 方法时,数据库列类型与 JavaScript 数据类型不匹配的问题。具体表现为在插入、更新或查询数据时,数据库操作失败或者数据类型不正确。

解决方案
确保数据库列类型与 JavaScript 数据类型的正确映射。在 `updateColumns` 方法中,已经有针对不同数据类型的映射逻辑。如果遇到新的数据类型,可以扩展这个映射逻辑,确保所有数据类型都能正确映射到数据库列类型。


 

问题2:查询结果为空


描述:在调用 `basic_query` 方法时,查询结果为空的情况。可能是由于查询条件设置不正确或者数据库中的数据不符合查询条件。

解决方案
在查询数据时,确保查询条件设置正确,并且数据库中有符合条件的数据。在 `basic_query` 方法中,调试日志可以帮助检查查询条件和结果。如果发现查询条件有误,及时调整查询逻辑。例如,在设置 `predicates` 时,确保 `like` 和 `equalTo` 条件正确使用。


总结

在本次实验中,我们详细探讨了如何为作业清单应用搭建关系型数据库,以满足其数据管理需求。我们从以下几个方面进行了深入研究和实践:

  1. 数据库设计过程:我们首先确定了数据库的整体架构和各个表的关系,确保能够高效地存储和管理作业清单应用中的各种数据。
  2. 表结构的定义:定义了任务表(TaskTable)及其字段,包括任务名称、截止日期、分类、完成状态等。这些字段能够全面描述任务的各个属性,为数据操作奠定基础。
  3. 数据的增删改查操作:实现了对数据库中数据的基本操作,包括插入新任务、更新现有任务、删除任务以及查询任务。我们利用这些操作实现了应用中的任务管理功能。
  4. 数据一致性和完整性:通过合理的设计和实现,确保在多用户同时操作时,数据的准确性和一致性不受影响。同时,采用适当的错误处理机制,保障数据库操作的可靠性。

通过本次实验,不仅成功搭建了关系型数据库,还掌握了在实际项目中使用数据库进行数据管理的实用技巧。这为后续功能的开发和应用的进一步优化提供了坚实的基础。

  • 21
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值