ORM数据库
ORM数据库是对象关系映射数据库的简称,HarmonyOS对象关系映射(Object Relational Mapping,ORM)数据库是一款基于SQLite的数据库框架,屏蔽了底层SQLite数据库的SQL操作,针对实体和关系提供了增删改查等一系列的面向对象接口。应用开发者不必再去编写复杂的SQL语句, 以操作对象的形式来操作数据库,提升效率的同时也能聚焦于业务开发。
基本概念
ORM数据库主要由数据库、实体对象、对象数据操作接口三个组件组成;通过谓词访问到应用持久化的关系型数据。通过将实例对象映射到关系上,实现操作实例对象的语法,来操作关系型数据库。它是在SQLite数据库的基础上提供的一个抽象层。主要运作机制如下图:
- 谓词
数据库中用来代表数据实体的性质、特征或者数据实体之间关系的词项,主要用来定义数据库的操作条件。对象关系映射数据库将SQLite数据库中的谓词封装成了接口方法供开发者调用。开发者通过对象数据操作接口,可以访问到应用持久化的关系型数据。 - 对象关系映射数据库
通过将实例对象映射到关系上,实现操作实例对象的语法,来操作关系型数据库。它是在SQLite数据库的基础上提供的一个抽象层。 - 对象关系映射数据库的三个主要组件:
- 数据库:
- 被开发者用@Database注解,且继承了OrmDatabase的类,对应关系型数据库。
- 实体对象:被开发者用@Entity注解,且继承了OrmObject的类,对应关系型数据库中的表。
- 对象数据操作接口:包括数据库操作的入口OrmContext类和谓词接口(OrmPredicate)等。
数据库的打开和加密
- 通过getOrmContext打开数据库,有以下不同的API参数
- 数据库加密
对象关系映射数据库提供数据库加密的能力,创建加密数据库时传入指定密钥,后续打开加密数据库时,需要传入正确密钥。
通过OrmConfig.Builder实现加密。
ORM数据库的操作
数据库的创建
ORM数据库由数据库的类,和数据表的类构成,并且在创建之前要添加相关jar包才能使用。
创建前配置
添加相关jar包
- 在build.gradle文件的ohos节点下添加
//添加以下代码 开启注解
compileOptions{
annotationEnabled true
}
//ohos节点完整代码
ohos {
compileSdkVersion 5
defaultConfig {
compatibleSdkVersion 4
}
buildTypes {
release {
proguardOpt {
proguardEnabled false
rulesFiles 'proguard-rules.pro'
}
}
}
//开启注解
compileOptions{
annotationEnabled true
}
}
- 在build.gradle文件的dependencies节点添加注解处理器
先来看一下官方文档的说明:
添加jar包,jar包的位置在我们安装的ide目录下->SDK->java-api下
添加orm包,jar包的位置在我们安装的ide目录下->SDK->java-build-tools-lib下
添加完成后配置如下:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
testImplementation 'junit:junit:4.13'
ohosTestImplementation 'com.huawei.ohos.testkit:runner:1.0.0.100'
compile files("E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\api\\ohos.jar",
"E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\build-tools\\lib\\orm_annotations_java.jar",
"E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\build-tools\\lib\\orm_annotations_processor_java.jar",
"E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\build-tools\\lib\\javapoet_java.jar")
annotationProcessor files("E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\build-tools\\lib\\orm_annotations_java.jar",
"E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\build-tools\\lib\\orm_annotations_processor_java.jar",
数据库创建前配置完成后,就可以使用orm数据库了。
创建数据库类
ORM数据库里面数据库类代表的就是数据库,要继承OrmDatabase,并使用@DataBase注解。
/**
* 创建数据库类
* entities 数据库里面的表对应的java类,可以是多个
* StudentTable.class 学生表
*
* version 数据库版本
* */
@Database(entities = {StudentTable.class},version = 1)
public abstract class SchoolDataBase extends OrmDatabase {
}
创建数据表类
ORM数据量里面数据库类代表数据库里面的数据库,要继承OrmObject,并使用@Entity注解。
/**
* tablename 表明
* indice 索引 @Index(value = {"firstTime","lastTime"} firstTime 和 lastTime组合起来不能重复
* unique = true 索引唯一
* time_index 索引名称
* */
@Entity(tableName = "student",indices = {@Index(value = {"firstTime","lastTime"},name = "time_index",unique = true)})
public class StudentTable extends OrmObject {
@PrimaryKey(autoGenerate = true)
private int studentId;
private String studentName;
private String firstTime;
private String lastTime;
public int getStudentId() {
return studentId;
}
public void setStudentId(int studentId) {
this.studentId = studentId;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public String getFirstTime() {
return firstTime;
}
public void setFirstTime(String firstTime) {
this.firstTime = firstTime;
}
public String getLastTime() {
return lastTime;
}
public void setLastTime(String lastTime) {
this.lastTime = lastTime;
}
}
创建数据库
通过DatabaseHelper的getOrmContext来创建ORM数据库,三个参数分别是数据库别名、数据库文件、对应的代表数据库类的java类。
//在配置和数据库类 数据库表都完成了
//创建数据库和表
DatabaseHelper helper = new DatabaseHelper(this);
//数据库的别名
//数据库类
helper.getOrmContext("SchoolDataBase","SchoolDataBase.db", SchoolDataBase.class);
通过以上步骤就可以创建ORM数据库了,并且数据库里面有一张Student的数据表。
ORM数据库增删改查
数据库的增删改查可以通过以下API进行实现,通过操作对象数据接口,实现增删改查的功能。
新增数据
ORM数据库通过对象的直接插入新增数据,不用编写sql语句。
- 拿到OrmContext操作对象
OrmContext schoolDataBase = helper.getOrmContext("SchoolDataBase", "SchoolDataBase.db", SchoolDataBase.class);
- 实例化新增的数据
//数据的新增
StudentTable tableInsert = new StudentTable();
tableInsert.setStudentName("李四");
tableInsert.setFirstTime("2014-9-10");
tableInsert.setLastTime("2018-7-6");
- 将数据插入到内存中
//insert 插入结果 true成功 false失败
//这里的数据是插入到内存中,并没有真正的把数据库落地到仓库
boolean insert = schoolDataBase.insert(tableInsert);
- 将内存里面的数据插入到数据库仓库里面去
boolean isFlush = schoolDataBase.flush();//将数据真正落地到仓库
只有当两个boolean都为true的时候,才说明数据已经插入到数据库里面去了,这里看一下控制台的结果。
查询数据
ORM数据库通过调用query进行查询,传入对应的谓词对象,或者谓词对象和指定返回字段的string数组。
/**
* 查询数据表StudentTable
* 里面firstTime等于2014 lastTime等于2018-7-6的数据
* */
OrmPredicates ormPredicates = schoolDataBase.where(StudentTable.class).equalTo("firstTime", "2014-9-10").and().equalTo("lastTime", "2018-7-6");
//只传谓词得到的是一个List集合
List<StudentTable> query = schoolDataBase.query(ormPredicates);
//循环打印数据
query.forEach(studentTable -> {
HiLog.info(logLabel,studentTable.getStudentName());
});
//传入谓词和string数组(指定返回字段),得到的是一个结果集
ResultSet query1 = schoolDataBase.query(ormPredicates, new String[]{"id", "studentName"});//指定返回的字段
HiLog.info(logLabel, Arrays.toString(query1.getAllColumnNames()));
数据的更新(修改)
- 方法一
先把需要修改的数据查询出来,然后修改,再写入到数据库里面去。
查询数据:
OrmPredicates ormPredicates = schoolDataBase.where(StudentTable.class).equalTo("firstTime", "2014-9-10").and().equalTo("lastTime", "2018-7-6");
//只传谓词得到的是一个List数组
List<StudentTable> query = schoolDataBase.query(ormPredicates);
修改数据:
StudentTable table = query.get(0);
table.setStudentName("改李四");
调用update API进行修改,并查询输出新数据:
//这里的boolean只是修改了内存
boolean update = schoolDataBase.update(table);
//通过flush修改数据库里面的数据
boolean flush = schoolDataBase.flush();
HiLog.info(logLabel,"update:" + update + " --:" + flush);
List<StudentTable> query2 = schoolDataBase.query(ormPredicates);
query2.forEach(studentTable -> {
HiLog.info(logLabel,"update:"+studentTable.getStudentName());
});
控制台结果:
- 方法二
通过传入谓词和值的封装类进行修改。
创建修改的谓词条件(修改studentName为李四的这条数据):
OrmPredicates ormUpdate = schoolDataBase.where(StudentTable.class).equalTo("studentName", "李四");
创建修改的值的封装类(将studentName修改为二改李四):
ValuesBucket bucket = new ValuesBucket();
bucket.putString("studentName","二改李四");
修改查询并在控制台输出结果:
//这里直接调用update方法,不需要额外调用flush就可以达到直接修改数据库里面数据的效果。
schoolDataBase.update(ormUpdate,bucket);
List<StudentTable> query2 = schoolDataBase.query(ormPredicates);
query2.forEach(studentTable -> {
HiLog.info(logLabel,"update:"+studentTable.getStudentName());
});
数据的删除
- 方法一
先将要删除的数据查询出来,然后进行删除,最后刷新数据库。
StudentTable tableDelete = query.get(0);
boolean delete = schoolDataBase.delete(tableDelete);
boolean flush = schoolDataBase.flush();
- 方法二
通过谓词,编写要删除的数据条件,然后调用api的delete方法,可以直接对数据库里面符合条件的数据进行删除。
OrmPredicates ormPredicatesDelete = schoolDataBase.where(StudentTable.class).equalTo("studentName", "李四");
int delete = schoolDataBase.delete(ormPredicatesDelete);
ORM事务处理
对象关系型数据库提供事务机制,来保证用户操作的原子性。对单条数据进行数据库操作时,无需开启事务;插入大量数据时,开启事务可以保证数据的准确性。如果中途操作出现失败,会自动执行回滚操作。
ORM事务有以下四个主要API:
- beginTransaction 开启事务
- commit 提交事务
- rollback 事务回滚
- isInTransaction 事务是否正在执行,返回一个boolean值
OrmContext支持标准的事务处理,通过一段简短的代码来看
对数据库的每一次操作,比如增删改查,都是一个单独的事务互不影响,而某些时候需要执行一些特定的操作,比如我要添加新数据,然后删除老数据,就需要让这两个处于通一个事务下执行;看以下例子代码:
schoolDataBase.beginTransaction();
try {
//添加
StudentTable tableInsert2 = new StudentTable();
tableInsert2.setStudentName("王五");
tableInsert2.setFirstTime("2014-9-10");
tableInsert2.setLastTime("2018-7-6");
schoolDataBase.insert(tableInsert2);
schoolDataBase.flush();
double c = 1/0;//被除数不能为0 这里会出现异常
//删除
OrmPredicates ormPredicatesDelete = schoolDataBase.where(StudentTable.class).equalTo("studentName", "李四");
int delete = schoolDataBase.delete(ormPredicatesDelete);
schoolDataBase.commit();
}catch (Exception e){
e.printStackTrace();
//出现异常,数据回滚
schoolDataBase.rollback();
}
- 首先我们是把添加和删除两个事务捆绑成了一个原子单元,所以要么同时成功,要么同时失败。
- 如果遇到异常会进catch,然后数据会回滚,添加和删除的操作都不会成功。
- 如果两个执行都成功,那么才是执行成功。
- 当然我们这里double c = 1/0;肯定是会出现异常的,在自己测试的时候可以注释掉这句代码,就可以查看成功时候的数据。
- 这里有一点需要注意:前面说到,每次操作数据库都是一次独立的事务,那么我们添加和删除的这串代码如果不放在同一个事务里面,执行的结果是添加成功,double c = 1/0;抛出异常,删除失败;所以处理几个相关逻辑的事务时,就需要把所有的事务都放在同一个事务单元里面,捆绑成一个原子单元,要么同时成功,要么失败。
- 以上原因也是为什么要使用事务的根本原因。
数据库变化添加观察者
通过使用对象数据操作接口,开发者可以在某些数据上设置观察者,接收数据变化的通知。
同样通过OrmContext提供的API来实现:
观察者只能监听观察到调用了flush的事务,没有调用flush的事务无法监听。
创建观察者:
public class OrmObjectObserver implements ohos.data.orm.OrmObjectObserver {
/**
* @param ormContext 数据库资源句柄
* @param allChangeToTarget 操作工具类
* */
@Override
public void onChange(OrmContext ormContext, AllChangeToTarget allChangeToTarget) {
//针对业务逻辑,做出符合业务逻辑的操作
//ormContext可以执行数据库的操作
//通过ormContext可以拿到最新添加到数据库里面记录的对应的student对象
// //可以通过工具类将数据保存到对应list里面去
// allChangeToTarget.addToDeletedList();
// allChangeToTarget.addToInsertList();
// allChangeToTarget.addToUpdatedList();
// //可以通过工具类将保存的数据取出
// allChangeToTarget.getDeletedList();
// allChangeToTarget.getInsertedList();
// allChangeToTarget.getUpdatedList();
}
}
给数据库添加注册观察者:
//注册观察者
//student 要观察的表
//OrmObjectObserver 回调
schoolDataBase.registerEntityObserver("student",new OrmObjectObserver());
数据库的备份恢复
开发者可以将当前数据库的数据进行备份,在必要的时候进行数据恢复。
数据库的备份和还原比较简单,在拿到ormContext之后调用相关API进行操作。
- 备份
//SchoolDataBaseBack.db 备份的数据库名称
schoolDataBase.backup("SchoolDataBaseBack.db");
- 还原
//SchoolDataBaseBack.db 将哪个数据库的数据进行还原
schoolDataBase.restore("SchoolDataBaseBack.db");
数据库的删除
在删除数据库之前要先关闭数据库,然后通过DataBaseHelper的删除api进行删除。
schoolDataBase.close();//先关掉
helper.deleteRdbStore("SchoolDataBase.db");//再删除
以上就是ORM数据库的相关操作。