鸿蒙开发实例|对象关系映射数据库

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: HarmonyOS应用数据管理不仅支持单设备的各种结构化数据的持久化,还支持跨设备之间数据的同步、共享及搜索功能,因此,开发者基于Harmony OS应用数据管理功能,能实现应用程序数据在不同终端设备之间的无缝衔接,从而保证用户在跨设备使用数据时所用数据的一致性。

HarmonyOS对象关系映射数据库是HarmonyOS中的本地数据库之一,是在SQLite数据库的基础上提供的一个抽象层。它屏蔽了底层SQLite数据库的SQL操作,将实例对象映射到关系上,并提供增、删、改、查等一系列面向对象的接口,使应用程序使用操作实例对象的语法来操作关系型数据库,因此,开发者可以不必编写那些复杂的SQL语句,从而既可以提升效率也能聚焦于业务开发。HarmonyOS中对象关系映射数据库的运作机制如图1所示。


从图1可以看出,对象关系映射数据库的3个主要组件包括:


(1) 数据库: 通过@Database注解,且继承自OrmDatabase的类,对应关系型数据库。


(2) 实体对象: 通过@Entity注解,且继承自OrmObject的类,对应关系型数据库中的表。


(3) 对象数据操作接口: 包括数据库操作的入口OrmContext 类和谓词接口(OrmPredicate)等。

image.png

图1 对象关系映射数据库的运作机制


创建Phone设备下的Java模板新项目。在进行开发之前,首先要进行build.gradle文件的配置,否则无法识别相关数据库的类的包。


一般情况下,使用的注解处理器的模块为com.huawei.ohos.hap模块,需要在模块的build.gradle文件的ohos节点中添加以下配置,代码如下:

compileOptions{
    annotationEnabled true    
}


如果使用注解处理器的模块为com.huawei.ohos.library,则需要在模块的build.gradle文件dependencies节点中配置注解处理器,此外,还需要在本地的HUAWEI SDK中找到orm_annotations_java.jar、orm_annotations_processor_java.jar和javapoet_java.jar这3个jar包的对应目录,并将这3个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的路径")
}


如果使用注解处理器的模块为java-library,则还需要导入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的路径")
}


配置完成之后,就可以开始新建数据库并对其进行操作了,具体步骤如下。


01、新建数据库及属性配置


创建数据库时,首先需要定义一个表示数据库的类,继承OrmDatabase,再通过@Database注解内的entities属性指定哪些数据模型类属于这个数据库,version属性指明数据库版本号。


在本例中,首先新建一个数据库类BookStore.java,选择entry→src→main→com.huawei.ormdb,右击选择并新建Class,命名为BookStore,如图2所示。

image.png

图2 新建一个数据库类


数据库类BookStore.java包含了User和Book两个表,版本号为1,将数据库类设置为虚类。具体代码如下:

import ohos.data.orm.OrmDatabase;
import ohos.data.orm.annotation.Database;
@Database(entities = {User.class, Book.class}, version = 1)
public abstract  class BookStore extends OrmDatabase {
}


02、构造数据表


构造数据表,即创建数据库实体类并配置对应的属性(如对应表的主键、外键等)。可通过创建一个继承了OrmObject并用@Entity注解的类,获取数据库实体对象,也就是表的对象。需要注意的是,数据表必须与其所在的数据库在同一个模块中。以新建的User表为例,新建的User类与BookStore类位于同一模块下,相应的目录如图3所示。

image.png

图3 BookStore数据库与User表位于同一模块


具体的构建过程代码如下:

//新建User表
import ohos.data.orm.OrmObject;
import ohos.data.orm.annotation.Entity;
import ohos.data.orm.annotation.Index;
import ohos.data.orm.annotation.PrimaryKey;
@Entity(tableName = "user", ignoredColumns = {"ignoreColumn1", "ignoreColumn2"},
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 ignoreColumn1;
    private int ignoreColumn2;
    //设置字段的getter和setter方法,此处仅给出示例,读者可以根据所设置的属性自行补全方法
    public void setBalance(double balance) {
        this.balance = balance;
    }
   ...
    public Integer getUserId() {
        return userId;
    }
   ...
}


在新建的User类中进行属性配置,tableName = "user"即在对应数据库内的表名为user,indices为属性列表,@Index注解的内容对应数据表索引的属性,本例中indices为firstName和lastName两个字段建立了复合索引,索引名为name_index,并且索引值是唯一的。ignoreColumns 表示该字段不需要添加到user 表的属性中,即类中定义的ignoreColumn1和ignoreColumn2不属于user表的属性。被@PrimaryKey注解的变量对应数据表的主键,一个表里只能有一个主键,在本例的user表中,将userId设为自增的主键。


数据库内还包含了Book表,Book表的构建和对其操作的实现过程同User表相同,具此处不再赘述其体实现。


03、创建数据库


在MainAbilitySlice的onStart()方法中完成数据库的创建,使用对象数据操作接口OrmContext创建数据库,实现代码如下:

public void onStart(Intent intent) {
   super.onStart(intent);
   super.setUIContent(ResourceTable.Layout_ability_main);
//使用对象数据操作接口OrmContext创建数据库
   DatabaseHelper helper = new DatabaseHelper(this);
   OrmContext context = helper.getOrmContext("BookStore", "BookStore.db", BookStore.class);
//对数据库进行操作
   //增加数据
     ...
   //查询数据
     ...
   //修改数据
     ...
   //删除数据
     ...
}


与构建关系型数据库不同的是,此处new DatabaseHelper(context)方法中context的入参类型为ohos.app.Context,必须直接传入slice而不能使用slice.getContext()获取context,否则会出现找不到类的报错。到这里,就成功创建了一个别名为BookStore且数据库文件名为BookStore.db的数据库。如果数据库已经存在,则执行上述代码并不会重复建库。通过context.getDatabaseDir()可以获取创建的数据库文件所在的目录。


04、数据操作


对象数据操作接口OrmContext提供了对数据库进行增、删、改、查的一系列方法,接下来进行详细介绍。


(1)增加数据 。

例如,在名为user 的表中,新建一个User 对象并设置其属性。OrmContext提供insert()方法将对象插入数据库。执行完insert()方法后,数据被保存在内存中,只有在flush()被调用后才会将数据持久化到数据库中。以HiLog形式显示插入数据后的user表,如图4所示。此处涉及对数据库的查询操作,将在稍后进行详细讲解。具体代码如下:

//增加数据
//新建User对象
User user = new User();
//设置对象属性
user.setUserId(0);
user.setFirstName("aa");
user.setLastName("AA");
user.setAge(22);
user.setBalance(120.51);
//再新建两个User对象,设置属性后将其持久化到数据库中,此处读者可以自行添加代码
...
//将新建对象插入并持久化到数据库中
boolean isSuccessed = context.insert(user);
isSuccessed = context.flush();
//以HiLog形式显示新增数据后的user表,以userID升序显示
HiLogLabel logLabel = new HiLogLabel(HiLog.LOG_APP,0,"OrmDB");
String s = new String("userID");
s = s.concat(" firstName");
s = s.concat(" lastName");
s = s.concat(" age");
s = s.concat(" balance");
HiLog.fatal(logLabel,"显示插入数据后的user表:");
HiLog.fatal(logLabel,s);
//查询数据
OrmPredicates query = context.where(User.class).orderByAsc("userID");
List<User> users = context.query(query);
int i = 0;
while (i != users.size()) {
            int id = users.get(i).getUserId();
            String s1 = "\t" + id + "\t\t";
            s1 = s1.concat(users.get(i).getFirstName() + "\t");
            s1 = s1.concat("\t\t" + users.get(i).getLastName());
            s1 = s1.concat("\t " + users.get(i).getAge() + "\t");
            s1 = s1.concat(" " + users.get(i).getBalance());
            HiLog.fatal(logLabel, s1);
            i = i + 1;
}


image.png


(2) 查询数据。

OrmContext提供query()方法查询满足指定条件的对象实例。例如,在user表中查询age=22的对象,在查询之前,依旧需要先设置谓词query1,利用query()方法查找user表中满足query1 的数据,得到一个User的列表user1,遍历user1,获取user1中各个对象的属性值,实现代码如下:

//查询age=22的数据并显示
//设置谓词
OrmPredicates query1 = context.where(User.class).equalTo("age", "22");
//查询
List<User> users1 = context.query(query1);
//将查询结果以HiLog形式显示
HiLogLabel logLabel1 = new HiLogLabel(HiLog.LOG_APP,0,"OrmDB");
HiLog.fatal(logLabel1,"显示user表中age值为22的数据:");
HiLog.fatal(logLabel1,s);
i = 0;
while (i != users1.size()){
     int id = users1.get(i).getUserId();
     String s1 = "\t" + id +"\t\t";
     s1 = s1.concat(users1.get(i).getFirstName()+"\t");
     s1 = s1.concat("\t\t"+users1.get(i).getLastName());
     s1 = s1.concat("\t "+users1.get(i).getAge()+"\t");
     s1 = s1.concat(" "+users1.get(i).getBalance());
     HiLog.fatal(logLabel1,s1);
     i = i + 1;
}


查询结果如图5所示。

image.png

图5 查询user表中age=22的数据


(3) 修改数据。

修改数据包括两种方式,一种是通过直接传入OrmObject对象的接口来更新数据,需要先从表中查到需要更新的结果对象列表,然后修改选定对象的值,再调用更新接口将数据持久化到数据库中。例如,将user表中age=39的数据的firstName更新为sd,需要先查找user表中对应的数据,得到一个结果列表,然后选择列表中需要更新的User对象,设置更新值,并调用update接口传入被更新的User对象。最后调用flush接口将数据持久化到数据库中。具体代码如下:

//更新数据
OrmPredicates predicates = context.where(User.class);
predicates.equalTo("age", 39);
//获取满足条件的数据集
List<User> users2 = context.query(predicates);
//选定要更新的数据
User userUD = users2.get(0);
//设置更新
userUD.setFirstName("sd");
context.update(userUD);
context.flush();
HiLog.fatal(logLabel, "显示更新数据后的user表:");
HiLog.fatal(logLabel, s);
query = context.where(User.class).orderByAsc("userID");
users = context.query(query);
i = 0;
while (i != users.size()) {
     int id = users.get(i).getUserId();
     String s1 = "\t" + id + "\t\t";
     s1 = s1.concat(users.get(i).getFirstName() + "\t");
     s1 = s1.concat("\t\t" + users.get(i).getLastName());
     s1 = s1.concat("\t " + users.get(i).getAge() + "\t");
     s1 = s1.concat(" " + users.get(i).getBalance());
     HiLog.fatal(logLabel, s1);
i = i + 1;
}


另一种方式,可以通过传入谓词的接口来更新和删除数据,方法与OrmObject对象的接口类似,只是无须flush就可以将数据持久化到数据库中。通过这种方式将user表中age=39的数据的firstName更新为sd,具体代码如下:

//使用valuesBucket来改变数据
ValuesBucket valuesBucket = new ValuesBucket();
valuesBucket.putString("firstName", "sd");
OrmPredicates update = context.where(User.class).equalTo("age", 39);
context.update(update, valuesBucket);


分别利用两种方式进行数据更新,更新后的结果如图6所示。

image.png


(4) 删除数据。

同修改数据一样,也包括两种方式。区别只是删除数据不需要更新对象的值。这里通过直接传入OrmObject对象的接口删除数据的方式删除满足firstName="aa"的第一个User对象,并用flush接口将数据持久化到数据库中,代码如下

//删除满足firstName = "aa"的第一个对象
OrmPredicates del = context.where(User.class).equalTo("firstName", "aa");
List<User> usersdel = context.query(del);
User userd = usersdel.get(0);
context.delete(userd);
context.flush();
HiLog.fatal(logLabel, "显示删除数据后的user表:");
HiLog.fatal(logLabel, s);
query = context.where(User.class).orderByAsc("userID");
users = context.query(query);
i = 0;
while (i != users.size()) {
     int id = users.get(i).getUserId();
     String s1 = "\t" + id + "\t\t";
     s1 = s1.concat(users.get(i).getFirstName() + "\t");
     s1 = s1.concat("\t\t" + users.get(i).getLastName());
s1 = s1.concat("\t " + users.get(i).getAge() + "\t");
     s1 = s1.concat(" " + users.get(i).getBalance());
     HiLog.fatal(logLabel, s1);
     i = i + 1;
}


显示删除数据后的表,如图7所示。

image.png

图7 删除数据后的结果显示


相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
8天前
|
Android开发
鸿蒙开发:自定义一个简单的标题栏
本身就是一个很简单的标题栏组件,没有什么过多的技术含量,有一点需要注意,当使用沉浸式的时候,注意标题栏的位置,需要避让状态栏。
鸿蒙开发:自定义一个简单的标题栏
|
8天前
|
API
鸿蒙开发:切换至基于rcp的网络请求
本文的内容主要是把之前基于http封装的库,修改为当前的Remote Communication Kit(远场通信服务),无非就是通信的方式变了,其他都大差不差。
鸿蒙开发:切换至基于rcp的网络请求
|
11天前
|
存储 SQL API
探索后端开发:构建高效API与数据库交互
【10月更文挑战第36天】在数字化时代,后端开发是连接用户界面和数据存储的桥梁。本文深入探讨如何设计高效的API以及如何实现API与数据库之间的无缝交互,确保数据的一致性和高性能。我们将从基础概念出发,逐步深入到实战技巧,为读者提供一个清晰的后端开发路线图。
|
13天前
|
UED
鸿蒙next版开发:相机开发-适配不同折叠状态的摄像头变更(ArkTS)
在HarmonyOS 5.0中,ArkTS提供了强大的相机开发能力,特别是针对折叠屏设备的摄像头适配。本文详细介绍了如何在ArkTS中检测和适配不同折叠状态下的摄像头变更,确保相机应用在不同设备状态下的稳定性和用户体验。通过代码示例展示了具体的实现步骤。
43 8
|
9天前
|
存储 缓存 NoSQL
2款使用.NET开发的数据库系统
2款使用.NET开发的数据库系统
|
13天前
|
API 内存技术
鸿蒙next版开发:相机开发-拍照(ArkTS)
在HarmonyOS 5.0中,ArkTS提供了一套完整的API来管理相机功能,特别是拍照功能。本文详细介绍如何在ArkTS中实现拍照功能,包括导入接口、创建会话、配置会话、触发拍照及监听拍照输出流状态,并提供代码示例进行详细解读。通过本文,你将掌握如何在HarmonyOS 5.0中使用ArkTS实现高效的拍照功能。
34 7
|
13天前
|
前端开发 API
鸿蒙next版开发:相机开发-预览(ArkTS)
在HarmonyOS 5.0中,使用ArkTS进行相机预览是核心功能之一。本文详细介绍了如何使用ArkTS实现相机预览,包括导入相机接口、创建Surface、获取相机输出能力、创建会话并开始预览,以及监听预览输出状态等步骤,并提供了代码示例。通过本文,读者可以掌握在HarmonyOS 5.0中使用ArkTS进行相机预览的基本方法。
35 6
|
13天前
|
编解码 开发工具 计算机视觉
鸿蒙5.0版开发:命令行工具(mediatool工具)
在HarmonyOS 5.0的开发中,命令行工具mediatool基于FFmpeg库,提供了丰富的媒体处理功能,如视频和音频的转码、封装格式转换、提取媒体信息等。本文详细介绍mediatool的功能和使用方法,并提供代码示例。
34 6
|
12天前
|
存储 SQL 数据库
深入浅出后端开发之数据库优化实战
【10月更文挑战第35天】在软件开发的世界里,数据库性能直接关系到应用的响应速度和用户体验。本文将带你了解如何通过合理的索引设计、查询优化以及恰当的数据存储策略来提升数据库性能。我们将一起探索这些技巧背后的原理,并通过实际案例感受优化带来的显著效果。
30 4
|
13天前
|
前端开发 开发者
鸿蒙next版开发:相机开发-元数据(ArkTS)
在HarmonyOS 5.0中,ArkTS新增了对相机元数据的访问能力,帮助开发者获取图像的详细信息。本文介绍了如何在ArkTS中获取和使用相机元数据,包括导入接口、创建元数据输出流、开启和停止元数据输出、监听元数据对象可用事件等步骤,并提供了详细的代码示例。
42 5
下一篇
无影云桌面