9afce6f6创建于 2025年5月7日历史提交
/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import dbUtils from '../utils/DBUtils';
import { Constants } from '../constants/Constants';
import { relationalStore, ValuesBucket } from '@kit.ArkData';
import CommonUtils from '../utils/CommonUtils';

/**
 * 数据库版本升级基础业务层
 */
export abstract class BaseDataService {
  async onUpgrade(targetVersion: number): Promise<void> {
    // 开启事务
    dbUtils.beginTransaction();
    // 获取当前数据库版本
    const oldVersion: number = dbUtils.getStoreVersion();
    // 将旧表改为临时表
    await dbUtils.updateTableName(Constants.STUDENT_TABLE, Constants.STUDENT_TABLE + oldVersion);
    // 创建新表
    const newTableColumnTypeMap: string[][] = CommonUtils.getTableColumnTypeMapByVersion(targetVersion);
    await dbUtils.createTable(Constants.STUDENT_TABLE, newTableColumnTypeMap);
    dbUtils.commit();
    // 自定义迁移逻辑
    const  LAST_ID: number = -1;
    const  FLAG: boolean = false;
    await this.migrate(LAST_ID, oldVersion, targetVersion, FLAG);
    // 删除旧表
    await dbUtils.dropTable(Constants.STUDENT_TABLE + oldVersion, targetVersion);
  }

  /**
   * 递归方式批次查询旧表数据
   * @param lastId 上一次查询的最后一个id
   * @param targetVersion 目标版本
   */
  private async migrate(lastId: number, oldVersion: number, targetVersion: number, flag: boolean): Promise<void> {
    if (flag) {
      return;
    }
    let newDataArray: ValuesBucket[] = new Array();
    await dbUtils.queryData(Constants.STUDENT_TABLE + oldVersion, Constants.MAX_BATCH_NUM, lastId, async (resultSet) => {
      if (resultSet.rowCount === 0) {
        flag = true;
        return;
      }
      // 对查询的旧表数据依次进行转换
      while (resultSet.goToNextRow()) {
        const  newData: ValuesBucket = this.transform(resultSet, targetVersion);
        newDataArray.push(newData);
        if (resultSet.isAtLastRow) {
          lastId = newData[Constants.ID_STR] as number;
          break;
        }
      }
      if (newDataArray.length === 0) {
        return;
      }
      // 将转换后的数据存入新表
      await dbUtils.batchInsert(Constants.STUDENT_TABLE, newDataArray);
      await this.migrate(lastId, oldVersion, targetVersion, flag);
    })
  }

  /**
   * TODO: 知识点: 新老版本字段转换逻辑(版本升级只需要实现这个方法即可)
   * @param resultSet 查询结果集
   * @param targetVersion 目标版本
   * @returns 目标版本格式数据
   */
  abstract transform(resultSet: relationalStore.ResultSet, targetVersion: number): ValuesBucket;
}

/**
 * V1版本升级数据处理业务层
 */
export class V1DataService extends BaseDataService {
  /**
   * V1新老版本字段转换逻辑
   * @param resultSet 查询结果集
   * @param targetVersion 目标版本
   * @returns 目标版本格式数据
   */
  transform(resultSet: relationalStore.ResultSet, targetVersion: number): ValuesBucket {
    switch (targetVersion) {
      case Constants.V2:
        return this.transformV1ToV2(resultSet);
      case Constants.V3:
        return this.transformV1ToV3(resultSet);
      default: {
        throw new Error('The database version to which you need to upgrade is incorrect');
      }
    }
  }

  private transformV1ToV3(resultSet: relationalStore.ResultSet): ValuesBucket {
    // 新增了个字段teacherFirstName,删除了个字段className
    const id: number = resultSet.getLong(resultSet.getColumnIndex(Constants.ID_STR));
    const name: string = resultSet.getString(resultSet.getColumnIndex(Constants.V1_STUDENT_COLUMN_TYPE_MAP[0][0]));
    const teacherFirstName: string = Constants.DEFAULT_TEACHER_FIRST_NAME;
    const newData: ValuesBucket = { 'id': id, 'name': name, 'teacherFirstName': teacherFirstName };
    return newData;
  }

  private transformV1ToV2(resultSet: relationalStore.ResultSet): ValuesBucket {
    // 新增了个字段teacherName,删除了个字段className
    const id: number = resultSet.getLong(resultSet.getColumnIndex(Constants.ID_STR));
    const name: string = resultSet.getString(resultSet.getColumnIndex(Constants.V1_STUDENT_COLUMN_TYPE_MAP[0][0]));
    const teacherName: string = Constants.DEFAULT_TEACHER_NAME;
    const newData: ValuesBucket = { 'id': id, 'name': name, 'teacherName': teacherName };
    return newData;
  }
}

/**
 * V2版本升级数据处理业务层
 */
export class V2DataService extends BaseDataService {
  /**
   * V2新老版本字段转换逻辑
   * @param resultSet 查询结果集
   * @param targetVersion 目标版本
   * @returns 目标版本格式数据
   */
  transform(resultSet: relationalStore.ResultSet, targetVersion: number): ValuesBucket {
    if (targetVersion === Constants.V3) {
      // 将teacherName字段改为teacherFirstName字段
      return this.transformV2ToV3(resultSet);
    } else {
      throw new Error('The database version to which you need to upgrade is incorrect');
    }
  }

  private transformV2ToV3(resultSet: relationalStore.ResultSet): ValuesBucket {
    const id: number = resultSet.getLong(resultSet.getColumnIndex(Constants.ID_STR));
    const name: string = resultSet.getString(resultSet.getColumnIndex(Constants.V2_STUDENT_COLUMN_TYPE_MAP[0][0]));
    const teacherName: string = resultSet.getString(resultSet.getColumnIndex(Constants.V2_STUDENT_COLUMN_TYPE_MAP[1][0]));
    const teacherFirstName: string = teacherName.split(Constants.EMPTY_STRING)[0];
    const newData: ValuesBucket = { 'id': id, 'name': name, 'teacherFirstName': teacherFirstName };
    return newData;
  }
}