기술나눔

[홍멍 연구 노트] 관계형 데이터베이스 개요

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

관계형 데이터베이스의 작동 메커니즘

1. 관계형 데이터베이스는 애플리케이션을 위한 공통 운영 인터페이스를 제공합니다. 기본 계층은 SQLite를 영구 스토리지 엔진으로 사용하고 트랜잭션, 인덱스, 뷰, 트리거, 외래 키, 매개변수화된 쿼리 및 SQLite의 데이터베이스 기능을 지원합니다. 예측을 컴파일합니다.
여기에 이미지 설명을 삽입하세요.

샘플 코드

일반적인 방법 DBUtils

import relationalStore from '@ohos.data.relationalStore'
import { common } from '@kit.AbilityKit'

export class DBUtils {
  // 数据库名称
  private tableName: string = 'accountTable'
  // 建表语句
  private sqlCreate: string = 'CREATE TABLE IF NOT EXISTS accountTable(id INTEGER PRIMARY KEY AUTOINCREMENT, accountType INTEGER, typeText TEXT, amount INTEGER)'
  // 表字段
  private columns: string[] = ['id', 'accountType', 'typeText', 'amount']
  // 数据库核心类
  private rdbStore: relationalStore.RdbStore | null = null
  // 数据库配置
  DB_CONFIG: relationalStore.StoreConfig = {
    name: 'RdbTest.db', // 数据库文件名
    securityLevel: relationalStore.SecurityLevel.S1, // 数据库安全级别
  };

  /**
   * 获取rdb
   * @param context:上下文
   * @param callback:回调函数,我们第一次获取数据时,需要在获取到rdb之后才能获取,所以有此回调
   */
  getRdbStore(context: common.UIAbilityContext, callback: Function) {
    relationalStore.getRdbStore(context, this.DB_CONFIG, (error, store) => {
      if (this.rdbStore !== null) {
        //如果已经有rdb,直接建表
        store.executeSql(this.sqlCreate)
        return
      }
      //保存rdb,下边会用
      this.rdbStore = store
      //建表
      store.executeSql(this.sqlCreate)
      console.log("test", "successed get dbStore")
      if (callback) callback()
    })
  }

  /**
   * 插入数据
   * @param data:数据对象
   * @param callback:回调函数,这里的结果是通过回调函数返回的(也可使用返回值)
   */
  insertData(data: AccountData, callback: Function) {
    //将数据对象,转换为ValuesBucket类型
    const valueBucket: relationalStore.ValuesBucket = generateValueBucket(data);
    // 调用insert插入数据
    this.rdbStore && this.rdbStore.insert(this.tableName, valueBucket, (err, res) => {
      if (err) {
        console.log("test,插入失败", err)
        callback(-1)
        return
      }
      console.log("test,插入成功", res)
      callback(res) //res为行号
    })
  }

  /**
   * 获取数据
   * @param callback:接收结果的回调函数
   */
  query(callback: Function) {
    //predicates是用于添加查询条件的
    let predicates = new relationalStore.RdbPredicates(this.tableName)

    // 查询所有,不需要条件
    // predicates.equalTo("字段",数据)
    this.rdbStore && this.rdbStore.query(predicates, this.columns, (error, resultSet: relationalStore.ResultSet) => {
      if (error) {
        console.log("test,获取数据失败", JSON.stringify(error))
        return
      }

      let rowCount: number = resultSet.rowCount
      console.log("test", "数据库中数据数量:" + rowCount) //没数据时返回-1或0
      if (rowCount <= 0 || typeof rowCount === 'string') {
        callback([])
        return
      }

      let result: AccountData[] = []
      //上来必须调用一次goToNextRow,让游标处于第一条数据,while(resultSet.goToNextRow())是最有写法
      while (resultSet.goToNextRow()) {
        let accountData: AccountData = { id: 0, accountType: 0, typeText: '', amount: 0 }
        accountData.id = resultSet.getDouble(resultSet.getColumnIndex('id'));
        accountData.typeText = resultSet.getString(resultSet.getColumnIndex('typeText'))
        accountData.accountType = resultSet.getDouble(resultSet.getColumnIndex('accountType'))
        accountData.amount = resultSet.getDouble(resultSet.getColumnIndex('amount'))
        result.push(accountData)
      }
      callback(result)
      resultSet.close() //释放数据集内容
    })
  }
}

function generateValueBucket(account: AccountData): relationalStore.ValuesBucket {
  let obj: relationalStore.ValuesBucket = {};
  obj.accountType = account.accountType;
  obj.typeText = account.typeText;
  obj.amount = account.amount;
  return obj;
}

export class AccountData {
  id: number = -1;
  accountType: number = 0;
  typeText: string = '';
  amount: number = 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112

색인 코드

import { AccountData, DBUtils } from '../uitls/DBUtils';
import { common } from '@kit.AbilityKit';

@Entry
@Component
struct Index_DBPage {
  // 数据库工具类
  private dbUtils: DBUtils = new DBUtils()
  private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext

  // 账户数据数组
  @State accountDataArray: AccountData[] = []
  // 列表的图片数组
  imageArr: Resource[] = [$r('app.media.foods'), $r('app.media.games'), $r('app.media.fuel')]

  // 添加数据弹框
  addDialogController: CustomDialogController = new CustomDialogController({
    builder: AddDialog({
      //点击确定的回调
      confirm: (insertData: AccountData) => {
        this.onConfirm(insertData)
      }
    })
  })

  // 界面打开时,查询数据,展示胡静
  aboutToAppear(): void {
    this.dbUtils.getRdbStore(this.context, () => {
      this.queryData()
    })
  }

  // 查询数据方法
  queryData() {
    this.dbUtils.query((result: AccountData[]) => {
      this.accountDataArray = result
      console.log("test,获取数据成功:", JSON.stringify(this.accountDataArray))
    })
  }

  // 点击确定回调
  onConfirm(insertData: AccountData) {
    console.log("test", JSON.stringify(insertData))
    // 插入数据
    this.dbUtils.insertData(insertData, (res: number) => {
      if (res > 0) {
        // AlertDialog.show({ message: "添加成功" })
        this.queryData()
      } else {
        AlertDialog.show({ message: "添加失败" })
      }
    })
  }

  build() {
    Stack() {
      Column() {
        Row() {
          Text('关系型数据库').height(33).fontSize(24).margin({ left: 24 }).fontColor(Color.Red)
        }.width('100%').justifyContent(FlexAlign.SpaceBetween).margin(12).backgroundColor(Color.Grey)

        //数据列表
        List({ space: 20 }) {
          ForEach(this.accountDataArray, (item: AccountData, index: number) => {
            ListItem() {
              Row() {
                // 图片
                Image(this.imageArr[item.accountType]).width(40).aspectRatio(1).margin({ right: 16 })
                // 内容
                Text(item.typeText).height(22).fontSize(16)
                Blank().layoutWeight(1)
                // 金额
                Text("¥: " + String(item.amount)).height(22).fontSize(16)
              }
              .width('90%')
              .padding({ left: 12, right: 12 })
              .margin({ left: 20 })
              .backgroundColor('#f1f3f5')
              .padding(10)
              .borderRadius(30)
            }
          })
        }
      }.width('100%')

      Button() {
        Image($r('app.media.add'))
      }.width(48).height(48).position({ x: '80%', y: '90%' })
      .onClick(() => {
        this.addDialogController.open()
      })
    }
  }
}

interface Item {
  icon: Resource;
  text: string;
}

@CustomDialog
struct AddDialog {
  controller: CustomDialogController;
  //确认回调
  confirm?: (insertData: AccountData) => void

  items: Array<Item> = [
    { icon: $r('app.media.foods'), text: '吃饭' },
    { icon: $r('app.media.games'), text: '娱乐' },
    { icon: $r('app.media.fuel'), text: '加油' },
  ]

  @State currentIndex: number = -1
  @State money: number = 0

  build() {
    Column() {
      Row() {
        ForEach(this.items, (item: Item, index) => {
          Column() {
            Image(item.icon).width(40).height(40)
            Text(item.text).fontSize(12).fontColor('#FF007DFF').margin({ top: 8 })
          }
          .width(86)
          .aspectRatio(1) //指定当前组件的宽高比
          .padding({ top: 12 })
          .margin({ top: 16, left: 12 })
          .align(Alignment.TopStart)
          .backgroundColor(this.currentIndex === index ? '#ccc' : '#FFF1F3F5')
          .borderRadius(16)
          .onClick(() => {
            this.currentIndex = index
          })
        })
      }.width('100%').justifyContent(FlexAlign.Center)

      Row() {
        Column() {
          Text('金额').width('100%').fontSize(20).fontColor(Color.Black)

          Column() {
            TextInput({
              placeholder: '请输入金额'
            })
              .padding({ left: 0, top: 0, bottom: 0 })
              .borderRadius(0)
              .backgroundColor(Color.White)
              .type(InputType.Number)
              .onChange((value: string) => {
                this.money = Number(value)
              })
          }.height(48).padding({ top: 15, bottom: 11 }).borderWidth({ bottom: 1 }).borderColor('#33182431')

          Button("确定").onClick((event: ClickEvent) => {
            if (this.currentIndex === -1) {
              AlertDialog.show({ message: "请选择种类" })
              return
            }
            if (this.money === 0) {
              AlertDialog.show({ message: "请输入金额" })
              return
            }
            let insertData: AccountData = {
              id: 0,
              accountType: this.currentIndex,
              typeText: this.items[this.currentIndex].text,
              amount: this.money
            }
            this.confirm && this.confirm(insertData)
            this.controller.close()
          }).width('90%').margin(20)
        }.width('100%').padding({ left: 12, right: 12 })
      }.width('100%').margin(20)
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176

효과

여기에 이미지 설명을 삽입하세요.