自學(xué)HarmonyOS應(yīng)用開發(fā)(63)- 對象關(guān)系映射數(shù)據(jù)庫升級

問題的背景
隨著應(yīng)用開發(fā)的不斷深入,或早或晚都會產(chǎn)生升級數(shù)據(jù)庫結(jié)構(gòu)的需求。這種升級可以是為特定的數(shù)據(jù)表添加字段,也可以是增加新表等。
以秒表應(yīng)用為例,升級之前的表構(gòu)成如下,這個數(shù)據(jù)庫中一共包含3個表:
(entities = {TimeRecord.class, TileData.class, Setting.class}, version = 1)public abstract class StopWatchDB extends OrmDatabase {}
假設(shè)我們需要增加第4個表TimingInfo。如果應(yīng)用還沒有發(fā)布,我們直接將這個表加進來,然后卸載應(yīng)用(這時會清除應(yīng)用數(shù)據(jù))就行了。
(entities = {TimeRecord.class, TileData.class, Setting.class, TimingInfo.class}, version = 1)public abstract class StopWatchDB extends OrmDatabase {}
但如果應(yīng)用已經(jīng)發(fā)布并被大量用戶使用,清除已有數(shù)據(jù)重新建庫的方法就不能用了。本文介紹在保留已有數(shù)據(jù)的情況下實現(xiàn)數(shù)據(jù)庫升級的方法。
升級數(shù)據(jù)庫版本
以下代碼是升級數(shù)據(jù)庫的第一步,增加新表和提升版本信息。
(entities = {TimeRecord.class, TileData.class, Setting.class, TimingInfo.class}, version = 2)public abstract class StopWatchDB extends OrmDatabase {}
注意第一行代碼的最后,version的值已經(jīng)修改為2。需要注意的是,版本號使用的是整數(shù)值。
實現(xiàn)數(shù)據(jù)庫升級類
如果只是修改數(shù)據(jù)庫版本信息,在實際使用增加的新表時,會發(fā)生下面的異常:

信息是需要的表不存在。要解決這個問題,獲取數(shù)據(jù)庫上下文時,要指定版本之間進行遷移的處理類。:
private OrmContext getOrmContext(){DatabaseHelper helper = new DatabaseHelper(this);return helper.getOrmContext("StopWatch","StopWatch.db",StopWatchDB.class,new TestOrmMigration12());}private static class TestOrmMigration12 extends OrmMigration {// 此處用于配置數(shù)據(jù)庫版本遷移的開始版本和結(jié)束版本,super(startVersion, endVersion)即數(shù)據(jù)庫版本號從1升到2。public TestOrmMigration12() {super(1, 2); }public void onMigrate(RdbStore rdbStore) {//數(shù)據(jù)庫升級處理}}
代碼第6行將TestOrmMigration12登錄到獲取數(shù)據(jù)庫上下文處理中,而代碼第11行指定了這個類用于版本1升級到版本2的處理。
數(shù)據(jù)升級處理
本例中增加了一個新的TimingInfo表,我們可以自己手寫增加表的語句,也可以參照開發(fā)工具自動生成的語句,這樣即省時省力,又能保證正確性。對于StopWatch應(yīng)用來說,我們可以從以下文件中找到對應(yīng)處理:
StopWatch\entry\build\generated\source\annotation\debug\xwg\stopwatch\db\StopWatchDBImpl.java
public void onCreate(RdbStore store) {store.executeSql("CREATE TABLE IF NOT EXISTS `setting` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `segment` TEXT , `item` TEXT , `value` TEXT )");store.executeSql("CREATE UNIQUE INDEX `index_setting_index` ON `setting` (`segment`,`item`)");store.executeSql("CREATE TABLE IF NOT EXISTS `TimingInfo` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `startTime` INTEGER , `title` TEXT )");store.executeSql("CREATE UNIQUE INDEX `index_time_index` ON `TimingInfo` (`startTime`)");store.executeSql("CREATE TABLE IF NOT EXISTS `time_record` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `recordId` INTEGER , `lapNumber` INTEGER , `time` INTEGER )");store.executeSql("CREATE UNIQUE INDEX `index_record_index` ON `time_record` (`recordId`,`lapNumber`)");store.executeSql("CREATE TABLE IF NOT EXISTS `tile_data` (`tileId` INTEGER PRIMARY KEY AUTOINCREMENT, `type` INTEGER , `zoom` INTEGER , `tileX` INTEGER , `tileY` INTEGER , `data` BLOB )");store.executeSql("CREATE UNIQUE INDEX `index_tile_index` ON `tile_data` (`type`,`zoom`,`tileX`,`tileY`)");}
代碼第5,6兩行就是我們想要的。將它拷貝粘貼到TestOrmMigration12的onMigrate方法中并稍加修改即可。
private static class TestOrmMigration12 extends OrmMigration {// 此處用于配置數(shù)據(jù)庫版本遷移的開始版本和結(jié)束版本,super(startVersion, endVersion)即數(shù)據(jù)庫版本號從1升到2。public TestOrmMigration12() {super(1, 2); }public void onMigrate(RdbStore rdbStore) {rdbStore.executeSql("CREATE TABLE IF NOT EXISTS `TimingInfo` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `startTime` INTEGER , `title` TEXT )");rdbStore.executeSql("CREATE UNIQUE INDEX `index_time_index` ON `TimingInfo` (`startTime`)");}}
參考代碼
完整代碼可以從以下鏈接下載:
https://github.com/xueweiguo/Harmony/tree/master/StopWatch
參考資料
開發(fā)-對象關(guān)系映射數(shù)據(jù)庫概述 (harmonyos.com)
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/database-orm-overview-0000000000030070
開發(fā)-對象關(guān)系映射數(shù)據(jù)庫開發(fā)指導(dǎo) (harmonyos.com)
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/database-orm-guidelines-0000000000030063
作者著作介紹
《實戰(zhàn)Python設(shè)計模式》是作者去年3月份出版的技術(shù)書籍,該書利用Python 的標(biāo)準(zhǔn)GUI 工具包tkinter,通過可執(zhí)行的示例對23 個設(shè)計模式逐個進行說明。這樣一方面可以使讀者了解真實的軟件開發(fā)工作中每個設(shè)計模式的運用場景和想要解決的問題;另一方面通過對這些問題的解決過程進行說明,讓讀者明白在編寫代碼時如何判斷使用設(shè)計模式的利弊,并合理運用設(shè)計模式。

對設(shè)計模式感興趣而且希望隨學(xué)隨用的讀者通過本書可以快速跨越從理解到運用的門檻;希望學(xué)習(xí)Python GUI 編程的讀者可以將本書中的示例作為設(shè)計和開發(fā)的參考;使用Python 語言進行圖像分析、數(shù)據(jù)處理工作的讀者可以直接以本書中的示例為基礎(chǔ),迅速構(gòu)建自己的系統(tǒng)架構(gòu)。
覺得本文有幫助?請分享給更多人。
關(guān)注微信公眾號【面向?qū)ο笏伎肌枯p松學(xué)習(xí)每一天!
面向?qū)ο箝_發(fā),面向?qū)ο笏伎迹?/span>
