HarmonyOS之数据管理·对象关系映射数据库的应用

举报
Serendipity·y 发表于 2022/02/16 23:50:03 2022/02/16
【摘要】 一、简介 ① 基本概念 HarmonyOS 对象关系映射(Object Relational Mapping,ORM)数据库是一款基于 SQLite 的数据库框架,屏蔽了底层 SQLite 数据库的 ...

一、简介

① 基本概念
  • HarmonyOS 对象关系映射(Object Relational Mapping,ORM)数据库是一款基于 SQLite 的数据库框架,屏蔽了底层 SQLite 数据库的 SQL 操作,针对实体和关系提供了增删改查等一系列的面向对象接口。应用开发者不必再去编写复杂的 SQL 语句, 以操作对象的形式来操作数据库,提升效率的同时也能聚焦于业务开发。
  • 对象关系映射数据库的三个主要组件:
    • 数据库:被开发者用 @Database 注解,且继承了 OrmDatabase 的类,对应关系型数据库。
    • 实体对象:被开发者用 @Entity 注解,且继承了 OrmObject 的类,对应关系型数据库中的表。
    • 对象数据操作接口:包括数据库操作的入口 OrmContext 类和谓词接口(OrmPredicate)等。
  • 谓词:数据库中是用来代表数据实体的性质、特征或者数据实体之间关系的词项,主要用来定义数据库的操作条件。对象关系映射数据库将 SQLite 数据库中的谓词封装成了接口方法供开发者调用。开发者通过对象数据操作接口,可以访问到应用持久化的关系型数据。
  • 对象关系映射数据库:通过将实例对象映射到关系上,实现使用操作实例对象的语法,来操作关系型数据库。它是在 SQLite 数据库的基础上提供的一个抽象层。
  • SQLite 数据库:一款轻型的数据库,是遵守 ACID 的关系型数据库管理系统。
② 运作机制
  • 对象关系映射数据库操作是基于关系型数据库操作接口完成的,实际是在关系型数据库操作的基础上又实现了对象关系映射等特性。因此对象关系映射数据库跟关系型数据库一样,都使用 SQLite 作为持久化引擎,底层使用的是同一套数据库连接池和数据库连接机制。
  • 使用对象关系映射数据库的开发者需要先配置实体模型与关系映射文件。应用数据管理框架提供的类生成工具会解析这些文件,生成数据库帮助类,这样应用数据管理框架就能在运行时,根据开发者的配置创建好数据库,并在存储过程中自动完成对象关系映射。开发者再通过对象数据操作接口,如 OrmContext 接口和谓词接口等操作持久化数据库。
  • 对象数据操作接口提供一组基于对象映射的数据操作接口,实现了基于 SQL 的关系模型数据到对象的映射,让用户不需要再和复杂的 SQL 语句打交道,只需简单地操作实体对象的属性和方法。对象数据操作接口支持对象的增删改查操作,同时支持事务操作等。
  • 对象关系映射数据库运作机制如下图所示:

在这里插入图片描述

③ 数据库配置
  • 如果不指定数据库的日志模式,那么系统默认日志方式是 WAL(Write Ahead Log)模式。
  • 如果不指定数据库的落盘模式,那么系统默认落盘方式是 FULL 模式。
  • HarmonyOS 数据库使用的共享内存默认大小是 2MB。
④ 使用限制
  • HarmonyOS 对象关系映射数据库是建立在关系型数据库的基础之上的,因此与关系型数据库一致:
    • 数据库中连接池的最大数量是 4 个,用以管理用户的读写操作。
    • 为保证数据的准确性,数据库同一时间只能支持一个写操作。
  • 实体对象属性支持的类型:
类型名称 描述 初始值
Integer 封装整型 null
int 整型 0
Long 封装长整型 null
long 长整型 0L
Double 封装双精度浮点型 null
double 双精度浮点型 0
Float 封装单精度浮点型 null
float 单精度浮点型 0
Short 封装短整型 null
short 短整型 0
String 字符串型 null
Boolean 封装布尔型 null
boolean 布尔型 0
Byte 封装字节型 null
byte 字节型 0
Character 封装字符型 null
char 字符型 ’ ’
Date 日期类 null
Time 时间类 null
Timestamp 时间戳类 null
Calendar 日历类 null
Blob 二进制大对象 null
Clob 字符大对象 null
⑤ 应用场景
  • 对象关系映射数据库适用于开发者使用的数据可以分解为一个或多个对象,且需要对数据进行增删改查等操作,但是不希望编写过于复杂的 SQL 语句的场景。
  • 该对象关系映射数据库的实现是基于关系型数据库,除了数据库版本升降级等场景外,操作对象关系映射数据库一般不需要编写 SQL 语句,但是仍然要求使用者对于关系型数据库的基本概念有一定的了解。

二、对象关系映射数据库 API

① 数据库和表的创建
  • 创建数据库:需要定义一个表示数据库的类,继承 OrmDatabase,再通过 @Database 注解内的 entities 属性指定哪些数据模型类属于该数据库。属性如下
    • version:数据库版本号;
    • entities:数据库内包含的表。
  • 创建数据表:可通过创建一个继承了 OrmObject 并用 @Entity 注解的类,获取数据库实体对象,也就是表的对象。属性如下:
    • tableName:表名;
    • primaryKeys:主键名,一个表里只能有一个主键,一个主键可以由多个字段组成;
    • foreignKeys:外键列表;
    • indices:索引列表。
  • 注解如下表所示:
接口名称 描述
@Database 被@Database注解且继承了OrmDatabase的类对应数据库类
@Entity 被@Entity注解且继承了OrmObject的类对应数据表类
@Column 被@Column注解的变量对应数据表的字段
@PrimaryKey 被@PrimaryKey注解的变量对应数据表的主键
@ForeignKey 被@ForeignKey注解的变量对应数据表的外键
@Index 被@Index注解的内容对应数据表索引的属性
② 数据库的加密
  • 对象关系映射数据库提供数据库加密的能力,创建数据库时传入指定密钥、创建加密数据库,后续打开加密数据库时,需要传入正确密钥。
  • 数据库传入密钥接口:
类名 接口名 描述
OrmConfig.Builder Builder setEncryptKey(byte[] encryptKey) 为数据库配置类设置数据库加密密钥,创建或打开数据库时传入包含数据库加密密钥的配置类,即可创建或打开加密数据库
③ 对象数据的增删改查
  • 通过对象数据操作接口,可以对对象数据进行增删改查操作。
  • 对象数据操作接口:
类名 接口名 描述
OrmContext boolean insert(T object) 添加方法
OrmContext boolean update(T object) 更新方法
OrmContext List query(OrmPredicates predicates) 查询方法
OrmContext boolean delete(T object) 删除方法
OrmContext OrmPredicates where(Class clz) 设置谓词方法
④ 对象数据的变化观察者设置
  • 通过使用对象数据操作接口,开发者可以在某些数据上设置观察者,接收数据变化的通知。
  • 数据变化观察者接口:
类名 接口名 描述
OrmContext void registerStoreObserver(String alias, OrmObjectObserver observer) 注册数据库变化回调
OrmContext void registerContextObserver(OrmContext watchedContext, OrmObjectObserver observer) 注册上下文变化回调
OrmContext void registerEntityObserver(String entityName, OrmObjectObserver observer) 注册数据库实体变化回调
OrmContext void registerObjectObserver(OrmObject ormObject, OrmObjectObserver observer) 注册对象变化回调
⑤ 数据库的升降级
  • 通过调用数据库升降级接口,开发者可以将数据库切换到不同的版本。
  • 数据库升降级接口:
类名 接口名 描述
OrmMigration public void onMigrate(int beginVersion, int endVersion) 数据库版本升降级接口
⑥ 数据库的备份恢复
  • 开发者可以将当前数据库的数据进行备份,在必要的时候进行数据恢复。
  • 数据库备份与恢复接口:
类名 接口名 描述
OrmContext boolean backup(String destPath) 数据库备份接口
OrmContext boolean restore(String srcPath); 数据库恢复备份接口

三、对象关系映射数据库的开发使用流程

① 配置“build.gradle”文件
  • 如果使用注解处理器的模块为“com.huawei.ohos.hap”模块,则需要在模块的“build.gradle”文件的“ohos”节点中添加以下配置:
	compileOptions{        
	    annotationEnabled true    
	} 

  
 
  • 1
  • 2
  • 3
  • 如果使用注解处理器的模块为“com.huawei.ohos.library”模块,则需要在模块的“build.gradle”文件的“dependencies”节点中配置注解处理器。查看“orm_annotations_java.jar”、“orm_annotations_processor_java.jar” 、“javapoet_java.jar”这3个 jar 包在 HUAWEI SDK 中的对应目录,并将目录的这三个 jar 包导进来。
	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.jar的路径", "javapoet_java.jar的路径")
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 如果使用注解处理器的模块为“java-library”模块,则需要在模块的“build.gradle”文件的“dependencies”节点中配置注解处理器,并导入“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
  • 2
  • 3
  • 4
② 构造数据库,即创建数据库类并配置对应的属性
  • 定义一个数据库类BookStore.java,数据库包含了“User”,“Book”,"AllDataType"三个表,版本号为“1”。数据库类的 getVersion 方法和 getHelper 方法不需要实现,直接将数据库类设为虚类即可:
	@Database(entities = {User.class, Book.class, AllDataType.class}, version = 1) 
	public abstract class BookStore extends OrmDatabase { 
	}

  
 
  • 1
  • 2
  • 3
③ 构造数据表
  • 即创建数据库实体类并配置对应的属性(如对应表的主键,外键等)。数据表必须与其所在的数据库在同一个模块中。
  • 例如,定义了一个实体类 User.java,对应数据库内的表名为“user”;indices 为“firstName”和“lastName”两个字段建立了复合索引“name_index”,并且索引值是唯一的;“ignoredColumns”表示该字段不需要添加到“user”表的属性中:
	@Entity(tableName = "user", ignoredColumns = {"ignoredColumn1", "ignoredColumn2"},
	    indices = {@Index(value = {"firstName", "lastName"}, name = "name_index", unique = true)}) 
	public class User extends OrmObject { 
	    // 此处将userId设为了自增的主键。注意只有在数据类型为包装类型时,自增主键才能生效。
	    @PrimaryKey(autoGenerate = true) 
	    private Integer userId;   
	    private String firstName;   
	    private String lastName;   
	    private int age;   
	    private double balance;   
	    private int ignoredColumn1; 
	    private int ignoredColumn2; 
	 
	    // 开发者自行添加字段的getter和setter方法。
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
④ 使用对象数据操作接口 OrmContext 创建数据库
  • 例如,通过对象数据操作接口OrmContext,创建一个别名为“BookStore”,数据库文件名为“BookStore.db”的数据库。如果数据库已经存在,执行以下代码不会重复创建。通过context.getDatabaseDir()可以获取创建的数据库文件所在的目录。
	DatabaseHelper helper = new DatabaseHelper(context); 
	          // context入参类型为ohos.app.Context,注意不要使用slice.getContext()来获取context,请直接传入slice,否则会出现找不到类的报错。
	OrmContext context = helper.getOrmContext("BookStore", "BookStore.db", BookStore.class); 

  
 
  • 1
  • 2
  • 3
⑤ (可选)数据库升降级
  • 如果开发者有多个版本的数据库,通过设置数据库版本迁移类可以实现数据库版本升降级。数据库版本升降级的调用示例如下,其中 BookStoreUpgrade 类也是一个继承了 OrmDatabase 的数据库类,与 BookStore 类的区别在于配置的版本号不同:
	OrmContext context = helper.getOrmContext("BookStore", 
	                                          "BookStore.db", 
	                                          BookStoreUpgrade.class, 
	                                          new TestOrmMigration32(), 
	                                          new TestOrmMigration23(), 
	                                          new TestOrmMigration12(), 
	                                          new TestOrmMigration21());

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • TestOrmMigration12 的实现示例如下:
	private static class TestOrmMigration12 extends OrmMigration {
	    // 此处用于配置数据库版本迁移的开始版本和结束版本,super(startVersion, endVersion)即数据库版本号从1升到2。
	    public TestOrmMigration12() {super(1, 2); }
	    @Override    
	    public void onMigrate(RdbStore store) {        
	        store.executeSql("ALTER TABLE `Book` ADD COLUMN `addColumn12` INTEGER");   
	    }
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
⑥ 使用对象数据操作接口 OrmContext 对数据库进行增删改查、注册观察者、备份数据库等
  • 增加数据,例如,在数据库的名为“user”的表中,新建一个 User 对象并设置对象的属性。直接传入 OrmObject 对象的增加接口,只有在 flush() 接口被调用后才会持久化到数据库中。
	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(); 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 更新或删除数据,分为两种情况:
    • 通过直接传入 OrmObject 对象的接口来更新数据,需要先从表中查到需要更新的 User 对象列表,然后修改对象的值,再调用更新接口持久化到数据库中。删除数据与更新数据的方法类似,只是不需要更新对象的值。例如,更新“user”表中 age 为“29”的行,需要先查找“user”表中对应数据,得到一个 User 的列表。然后选择列表中需要更新的 User 对象(如第0个对象),设置需要更新的值,并调用 update 接口传入被更新的 User 对象,最后调用 flush 接口持久化到数据库中:
	// 更新数据
	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();
	
	// 删除数据
	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();

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
    • 通过传入谓词的接口来更新和删除数据,方法与 OrmObject 对象的接口类似,只是无需 flush 就可以持久化到数据库中:
	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);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 查询数据。在数据库的“user”表中查询lastName为“San”的User对象列表,示例如下:
	OrmPredicates query = context.where(User.class).equalTo("lastName", "San"); 
	List<User> users = context.query(query);

  
 
  • 1
  • 2
  • 注册观察者:
	// 定义一个观察者类。
	private class MyOrmObjectObserver implements OrmObjectObserver {
	    @Override    
	    public void onChange(OrmContext changeContext, AllChangeToTarget subAllChange) {
	        // 用户可以在此处定义观察者行为
	    }
	}
	
	// 调用registerEntityObserver方法注册一个观察者observer。
	MyOrmObjectObserver observer = new MyOrmObjectObserver();
	context.registerEntityObserver("user", observer);
	
	// 当以下方法被调用,并flush成功时,观察者observer的onChange方法会被触发。其中,方法的入参必须为User类的对象。
	public <T extends OrmObject> boolean insert(T object)
	public <T extends OrmObject> boolean update(T object)
	public <T extends OrmObject> boolean delete(T object)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 备份数据库。其中原数据库名为“OrmBackup.db”,备份数据库名为“OrmBackup001.db”:
	OrmContext context = helper.getObjectContext("OrmBackup", "OrmBackup.db", BookStore.class);
	context.backup("OrmBackup001.db");
	context.close();

  
 
  • 1
  • 2
  • 3
⑦ 删除数据库
	helper.deleteRdbStore("OrmBackup.db");

  
 
  • 1

四、完整示例

文章来源: blog.csdn.net,作者:Serendipity·y,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/Forever_wj/article/details/118655258

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。