鴻蒙OS 對(duì)象關(guān)系映射數(shù)據(jù)庫開發(fā)指導(dǎo)

2020-09-18 16:08 更新

場(chǎng)景介紹

對(duì)象關(guān)系映射數(shù)據(jù)庫適用于開發(fā)者使用的數(shù)據(jù)可以分解為一個(gè)或多個(gè)對(duì)象,且需要對(duì)數(shù)據(jù)進(jìn)行增刪改查等操作,但是不希望編寫過于復(fù)雜的 SQL 語句的場(chǎng)景。

該對(duì)象關(guān)系映射數(shù)據(jù)庫的實(shí)現(xiàn)是基于關(guān)系型數(shù)據(jù)庫,除了數(shù)據(jù)庫版本升降級(jí)等場(chǎng)景外,操作對(duì)象關(guān)系映射數(shù)據(jù)庫一般不需要編寫 SQL 語句,但是仍然要求使用者對(duì)于關(guān)系型數(shù)據(jù)庫的基本概念有一定的了解。

開發(fā)能力介紹

對(duì)象關(guān)系映射數(shù)據(jù)庫目前可以支持?jǐn)?shù)據(jù)庫和表的創(chuàng)建,對(duì)象數(shù)據(jù)的增刪改查、對(duì)象數(shù)據(jù)變化回調(diào)、數(shù)據(jù)庫升降級(jí)和備份等功能。

數(shù)據(jù)庫和表的創(chuàng)建

  1. 創(chuàng)建數(shù)據(jù)庫。開發(fā)者需要定義一個(gè)表示數(shù)據(jù)庫的類,繼承 OrmDatabase,再通過 @Database 注解內(nèi)的 entities 屬性指定哪些數(shù)據(jù)模型類屬于這個(gè)數(shù)據(jù)庫。

屬性:

  • version:數(shù)據(jù)庫版本號(hào)。
  • entities:數(shù)據(jù)庫內(nèi)包含的表。

  1. 創(chuàng)建數(shù)據(jù)表。開發(fā)者可通過創(chuàng)建一個(gè)繼承了OrmObject 并用 @Entity 注解的類,獲取數(shù)據(jù)庫實(shí)體對(duì)象,也就是表的對(duì)象。

屬性:

  • tableName:表名。
  • primaryKeys:主鍵名,一個(gè)表里只能有一個(gè)主鍵,一個(gè)主鍵可以由多個(gè)字段組成。
  • foreignKeys:外鍵列表。
  • indices:索引列表。
接口名稱 描述
@Database 被 @Database注解且繼承了 OrmDatabase 的類對(duì)應(yīng)數(shù)據(jù)庫類。
@Entity 被 @Entity注解且繼承了 OrmObject 的類對(duì)應(yīng)數(shù)據(jù)表類。
@Column 被 @Column 注解的變量對(duì)應(yīng)數(shù)據(jù)表的字段。
@PrimaryKey 被 @PrimaryKey 注解的變量對(duì)應(yīng)數(shù)據(jù)表的主鍵。
@ForeignKey 被 @ForeignKey 注解的變量對(duì)應(yīng)數(shù)據(jù)表的外鍵。
@Index 被 @Index 注解的內(nèi)容對(duì)應(yīng)數(shù)據(jù)表索引的屬性。

數(shù)據(jù)庫的加密

對(duì)象關(guān)系映射數(shù)據(jù)庫提供數(shù)據(jù)庫加密的能力,創(chuàng)建數(shù)據(jù)庫時(shí)傳入指定密鑰、創(chuàng)建加密數(shù)據(jù)庫,后續(xù)打開加密數(shù)據(jù)庫時(shí),需要傳入正確密鑰。

類名 接口名 描述
OrmConfig.Builder Builder setEncryptKey(byte[] encryptKey) 為數(shù)據(jù)庫配置類設(shè)置數(shù)據(jù)庫加密密鑰,創(chuàng)建或打開數(shù)據(jù)庫時(shí)傳入包含數(shù)據(jù)庫加密密鑰的配置類,即可創(chuàng)建或打開加密數(shù)據(jù)庫。

對(duì)象數(shù)據(jù)的增刪改查

通過對(duì)象數(shù)據(jù)操作接口,開發(fā)者可以對(duì)對(duì)象數(shù)據(jù)進(jìn)行增刪改查操作。

類名 接口名稱 描述
OrmContext <T extends OrmObject> boolean insert(T object) 添加方法。
OrmContext <T extends OrmObject> boolean update(T object) 更新方法。
OrmContext <T extends OrmObject> List<T> query(OrmPredicates predicates) 查詢方法。
OrmContext <T extends OrmObject> boolean delete(T object) 刪除方法。
OrmContext <T extends OrmObject> OrmPredicates where(Class<T> clz) 設(shè)置謂詞方法。

對(duì)象數(shù)據(jù)的變化觀察者**設(shè)置**

通過使用對(duì)象數(shù)據(jù)操作接口,開發(fā)者可以在某些數(shù)據(jù)上設(shè)置觀察者,接收數(shù)據(jù)變化的通知。

類名 接口名稱 描述
OrmContext void registerStoreObserver(String alias, OrmObjectObserver observer) 注冊(cè)數(shù)據(jù)庫變化回調(diào)。
OrmContext void registerContextObserver(OrmContext watchedContext, OrmObjectObserver observer) 注冊(cè)上下文變化回調(diào)。
OrmContext void registerEntityObserver(String entityName, OrmObjectObserver observer) 注冊(cè)數(shù)據(jù)庫實(shí)體變化回調(diào)。
OrmContext void registerObjectObserver(OrmObject ormObject, OrmObjectObserver observer) 注冊(cè)對(duì)象變化回調(diào)。

數(shù)據(jù)庫的升降級(jí)

通過調(diào)用數(shù)據(jù)庫升降級(jí)接口,開發(fā)者可以將數(shù)據(jù)庫切換到不同的版本。

類名 接口名稱 描述
OrmMigration public void onMigrate(int beginVersion, int endVersion) 數(shù)據(jù)庫版本升降級(jí)接口。

數(shù)據(jù)庫的備份恢復(fù)

開發(fā)者可以將當(dāng)前數(shù)據(jù)庫的數(shù)據(jù)進(jìn)行備份,在必要的時(shí)候進(jìn)行數(shù)據(jù)恢復(fù)。

類名 接口名稱 描述
OrmContext boolean backup(String destPath) 數(shù)據(jù)庫備份接口。
OrmContext boolean restore(String srcPath); 數(shù)據(jù)庫恢復(fù)備份接口。

開發(fā)步驟

  1. 配置“build.gradle”文件。

  • 如果使用注解處理器的模塊為“com.huawei.ohos.hap”模塊,則需要在模塊的“build.gradle”文件的“ohos”節(jié)點(diǎn)中添加以下配置:

     compileOptions{            annotationEnabled true    } 

  • 如果使用注解處理器的模塊為“com.huawei.ohos.library”模塊,則需要在模塊的“build.gradle”文件的“dependencies”節(jié)點(diǎn)中配置注解處理器。查看“orm_annotations_java.jar”、“orm_annotations_processor_java.jar” 、“javapoet_java.jar”

這3個(gè) jar 包在 HUAWEI SDK 中的對(duì)應(yīng)目錄,并將目錄的這三個(gè) jar 包導(dǎo)進(jìn)來。

     dependencies {
         compile files("orm_annotations_java.jar 的路徑","orm_annotations_processor_java.jar 的路徑","javapoet_java.jar 的路徑")
         annotationProcessor files("orm_annotations_java.jar 的路徑","orm_annotations_processor_java.ja 的路徑","javapoet_java.jar 的路徑")
     }

  • 如果使用注解處理器的模塊為“java-library”模塊,則需要在模塊的“build.gradle”文件的“dependencies”節(jié)點(diǎn)中配置注解處理器,并導(dǎo)入“ohos.jar”。

     dependencies {
         compile files("ohos.jar 的路徑","orm_annotations_java.jar 的路徑","orm_annotations_processor_java.jar 的路徑","javapoet_java.jar 的路徑")     
         annotationProcessor files("orm_annotations_java.jar 的路徑","orm_annotations_processor_java.jar 的路徑","javapoet_java.jar 的路徑")
     }

  1. 構(gòu)造數(shù)據(jù)庫,即創(chuàng)建數(shù)據(jù)庫類并配置對(duì)應(yīng)的屬性。

例如,定義了一個(gè)數(shù)據(jù)庫類 BookStore.java,數(shù)據(jù)庫包含了“User”,"Book","AllDataType"三個(gè)表,版本號(hào)為 “1”。數(shù)據(jù)庫類的 getVersion 方法和 getHelper 方法不需要實(shí)現(xiàn),直接將數(shù)據(jù)庫類設(shè)為虛類即可。

   @Database(entities = {User.class, Book.class, AllDataType.class}, version = 1) 
   public abstract class BookStore extends OrmDatabase { 
   }

  1. 構(gòu)造數(shù)據(jù)表,即創(chuàng)建數(shù)據(jù)庫實(shí)體類并配置對(duì)應(yīng)的屬性(如對(duì)應(yīng)表的主鍵,外鍵等)。數(shù)據(jù)表必須與其所在的數(shù)據(jù)庫在同一個(gè)模塊中。

例如,定義了一個(gè)實(shí)體類 User.java,對(duì)應(yīng)數(shù)據(jù)庫內(nèi)的表名為“user”;indices 為“firstName”和“l(fā)astName”兩個(gè)字段建立了復(fù)合索引“name_index”,并且索引值是唯一的;“ignoreColumns”表示該字段不需要添加到“user”表的屬性中。

   @Entity(tableName = "user", ignoredColumns = {"ignoreColumn1", "ignoreColumn2"},
       indices = {@Index(value = {"firstName", "lastName"}, name = "name_index", unique = true)}) 
   public class User extends OrmObject { 
       // 此處將userId設(shè)為了自增的主鍵。注意只有在數(shù)據(jù)類型為包裝類型時(shí),自增主鍵才能生效。
       @PrimaryKey(autoGenerate = true) 
       private Integer userId;   
       private String firstName;   
       private String lastName;   
       private int age;   
       private double balance;   
       private int ignoreColumn1; 
       private int ignoreColumn2; 

    
       // 開發(fā)者自行添加字段的getter和setter 方法。 
   }

說明

示例中的 getter & setter 的方法名為小駝峰格式,除了手寫方法,IDE 中包含自動(dòng)生成 getter 和setter 方法的 Generate 插件。

  • 當(dāng)變量名的格式類似“firstName”時(shí),getter 和 setter 方法名應(yīng)為“getFirstName”和“setFirstName”。
  • 當(dāng)變量名的格式類似“mAge”,即第一個(gè)字母小寫,第二個(gè)字母大寫的格式時(shí),getter 和 setter 方法名應(yīng)為“getmAge”和“setmAge”。
  • 當(dāng)變量名格式類似“x”,即只有一個(gè)字母時(shí), getter 和 setter 方法名應(yīng)為“getX”和“setX”。

變量為 boolean 類型時(shí),上述規(guī)則仍然成立,即“isFirstName”,“ismAge”,“isX”。

  1. 使用對(duì)象數(shù)據(jù)操作接口 OrmContext 創(chuàng)建數(shù)據(jù)庫。

例如,通過對(duì)象數(shù)據(jù)操作接口 OrmContext,創(chuàng)建一個(gè)別名為“BookStore”,數(shù)據(jù)庫文件名為“BookStore.db”的數(shù)據(jù)庫。如果數(shù)據(jù)庫已經(jīng)存在,執(zhí)行以下代碼不會(huì)重復(fù)創(chuàng)建。通過 context.getDatabaseDir()可以獲取創(chuàng)建的數(shù)據(jù)庫文件所在的目錄。

   DatabaseHelper helper = new DatabaseHelper(context); // context入?yún)㈩愋蜑閛hos.app.Context,注意不要使用slice.getContext()來獲取context,請(qǐng)直接傳入slice,否則會(huì)出現(xiàn)找不到類的報(bào)錯(cuò)。
   OrmContext context = helper.getOrmContext("BookStore", "BookStore.db", BookStore.class); 

  1. (可選)數(shù)據(jù)庫升降級(jí)。如果開發(fā)者有多個(gè)版本的數(shù)據(jù)庫,通過設(shè)置數(shù)據(jù)庫版本遷移類可以實(shí)現(xiàn)數(shù)據(jù)庫版本升降級(jí)。

數(shù)據(jù)庫版本升降級(jí)的調(diào)用示例如下。其中 BookStoreUpgrade 類也是一個(gè)繼承了 OrmDatabase 的數(shù)據(jù)庫類,與 BookStore 類的區(qū)別在于配置的版本號(hào)不同。

   OrmContext context = helper.getOrmContext("BookStore", "BookStore.db", BookStoreUpgrade.class, new TestOrmMigration32(), new TestOrmMigration23(), new TestOrmMigration12(), new TestOrmMigration21());

TestOrmMigration12 的實(shí)現(xiàn)示例如下:

   private static class TestOrmMigration12 extends OrmMigration {
       // 此處用于配置數(shù)據(jù)庫版本遷移的開始版本和結(jié)束版本,super(startVersion, endVersion)即數(shù)據(jù)庫版本號(hào)從1升到2。
       public TestOrmMigration12() {super(1, 2); }
       @Override    
       public void onMigrate(RdbStore store) {        
           store.executeSql("ALTER TABLE `Book` ADD COLUMN `addColumn12` INTEGER");   
       }
   }

說明

數(shù)據(jù)庫版本遷移類的起始版本和結(jié)束版本必須是連續(xù)的。

  • 如果 BookStoreUpgrad e類的版本號(hào)配置為“2”,而當(dāng)前 BookStore.db 的實(shí)際版本號(hào)為“1”時(shí),TestOrmMigration12 類的 onMigrate 方法會(huì)自動(dòng)被調(diào)用。開發(fā)者可在 onMigrate 方法中填寫升級(jí)需要執(zhí)行的 sql 語句。
  • 如果 BookStoreUpgrade 的類版本號(hào)配置為“3”,而當(dāng)前 BookStore.db 的實(shí)際版本號(hào)為“1”時(shí),TestOrmMigration12, TestOrmMigration23 的 onMigrate 方法會(huì)自動(dòng)被調(diào)用完成數(shù)據(jù)庫升級(jí)。數(shù)據(jù)庫版本降級(jí)同理。

  1. 使用對(duì)象數(shù)據(jù)操作接口 OrmContext 對(duì)數(shù)據(jù)庫進(jìn)行增刪改查、注冊(cè)觀察者、備份數(shù)據(jù)庫等。

  • 增加數(shù)據(jù)。例如,在數(shù)據(jù)庫的名為“user”的表中,新建一個(gè) User 對(duì)象并設(shè)置對(duì)象的屬性。直接傳入 OrmObject 對(duì)象的增加接口,只有在 flush() 接口被調(diào)用后才會(huì)持久化到數(shù)據(jù)庫中。

     User user = new User(); 
     user.setFirstName("Zhang"); 
     user.setLastName("San"); 
     user.setAge(29); 
     user.setBalance(100.51); 
     boolean isSuccessed = context.insert(user); 
     isSuccessed = context.flush(); 

  • 更新或刪除數(shù)據(jù),分為兩種情況:

  • 通過直接傳入 OrmObject 對(duì)象的接口來更新數(shù)據(jù),需要先從表中查到需要更新的 User 對(duì)象列表,然后修改對(duì)象的值,再調(diào)用更新接口持久化到數(shù)據(jù)庫中。刪除數(shù)據(jù)與更新數(shù)據(jù)的方法類似,只是不需要更新對(duì)象的值。

例如,更新“user”表中age為“29”的行,需要先查找“user”表中對(duì)應(yīng)數(shù)據(jù),得到一個(gè) User 的列表。然后選擇列表中需要更新的 User 對(duì)象(如第 0 個(gè)對(duì)象),設(shè)置需要更新的值,并調(diào)用 update 接口傳入被更新的 User 對(duì)象。最后調(diào)用 flush 接口持久化到數(shù)據(jù)庫中。

       // 更新數(shù)據(jù)
       OrmPredicates predicates = context.where(User.class);
       predicates.equalTo("age",29);
       List<User> users = context.query(predicates);
       User user = users.get(0);
       user.setFirstName("Li");
       context.update(user);
       context.flush();

        
       // 刪除數(shù)據(jù)
       OrmPredicates predicates = context.where(User.class);
       predicates.equalTo("age",29);
       List<User> users = context.query(predicates);
       User user = users.get(0);
       context.delete(user);
       context.flush();

  • 通過傳入謂詞的接口來更新和刪除數(shù)據(jù),方法與 OrmObject 對(duì)象的接口類似,只是無需 flush 就可以持久化到數(shù)據(jù)庫中。

       ValuesBucket valuesBucket = new ValuesBucket();
       valuesBucket.putInteger("age", 31);
       valuesBucket.putString("firstName", "ZhangU");
       valuesBucket.putString("lastName", "SanU");
       valuesBucket.putDouble("balance", 300.51);
       OrmPredicates update = context.where(User.class).equalTo("userId", 1);
       context.update(update, valuesBucket);

  • 查詢數(shù)據(jù)。在數(shù)據(jù)庫的“user”表中查詢lastName為“San”的 User 對(duì)象列表,示例如下:

     OrmPredicates query = context.where(User.class).equalTo("lastName", "San"); 
     List<User> users = context.query(query);

  • 注冊(cè)觀察者。

     // 定義一個(gè)觀察者類。
     private class MyOrmObjectObserver implements OrmObjectObserver {
         @Override    
         public void onChange(OrmContext changeContext,AllChangeToTarget subAllChange {
             // 用戶可以在此處定義觀察者行為
         }
     }

      
     // 調(diào)用registerEntityObserver方法注冊(cè)一個(gè)觀察者observer。
     MyOrmObjectObserver observer = new MyOrmObjectObserver();
     context.registerEntityObserver("user", observer);

      
     // 當(dāng)以下方法被調(diào)用,并flush成功時(shí),觀察者observer的onChange方法會(huì)被觸發(fā)。其中,方法的入?yún)⒈仨殲閁ser類的對(duì)象。
     public <T extends OrmObject> boolean insert(T object)
     public <T extends OrmObject> boolean update(T object)
     public <T extends OrmObject> boolean delete(T object)

  • 備份數(shù)據(jù)庫。其中原數(shù)據(jù)庫名為“OrmBackUp.db”,備份數(shù)據(jù)庫名為“OrmBackup001.db”。

     OrmContext context = helper.getObjectContext("OrmBackup", "OrmBackup.db", BookStore.class);
     context.backup("OrmBackup001.db");
     context.close();

  1. 刪除數(shù)據(jù)庫,例如刪除 OrmBackup.db。

   helper.deleteRdbStore("OrmBackup.db");
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)