> 文档中心 > HarmonyOS数据库之关系型数据库

HarmonyOS数据库之关系型数据库

关系型数据库的操作及管理

      • 基础概述
      • 关系型数据库创建前的配置
        • 自定义数据库配置
        • 打开加密的关系型数据库
      • 关系型数据库的增删改查
        • 创建数据库
        • 新增数据
        • 查询数据
        • 更新数据
        • 删除数据

已经鸽了很久了,今天也准备了点新东西来进行发布,在搞Android的时候我们都知道有SQlite数据库以及AndroidX之后的ROOM数据库,一些轻量级的数据就可以存储在数据库里面;HarmonyOS同样提供了数据库的相关操作以及管理。

基础概述

关系型数据库(Relational Database,RDB)是一种基于关系模型来管理数据的数据库,创建在关系模型基础上的数据库,以行和列的形式存储数据。。HarmonyOS关系型数据库基于SQLite组件提供了一套完整的对本地数据库进行管理的机制,对外提供了一系列的增、删、改、查接口,也可以直接运行用户输入的SQL语句来满足复杂的场景需要。HarmonyOS提供的关系型数据库功能更加完善,查询效率更高。

关系型数据库创建前的配置

在创建数据库前我们要配置数据库名称、存储模式、日志模式、同步模式、是否为只读模式以及对数据库进行加密;使用StoreConfig.Builder里面的builder()内部类进行配置;通过StoreConfig我们同样可以获取到一个关系型数据库的基本配置信息,主要以下七项:

  • config.getName() 获取数据库名称
  • config.isReadOnly() 设置数据库是否是只读模式 ,默认是false
  • config.getDatabaseFileType() 设置数据库的文件类型,默认是NORMAL
  • config.getJournalMode() 设置数据库的日志模式,默认是null
  • config.getStorageMode() 设置数据库的存储模式,默认是磁盘
  • config.getSyncMode() 设置数据库的同步模式,默认是null
  • config.getEncryptKey() 设置数据库密钥,默认是开放的,不加密的
StoreConfig config = StoreConfig.newDefaultConfig("DemoSql.db");//后缀dbSystem.out.println(config.getName());//数据库名称System.out.println(config.isReadOnly());//是否只读  -- 默认falseSystem.out.println(config.getDatabaseFileType());//数据库 -- 默认 NORMALSystem.out.println(config.getJournalMode());//日志模式 nullSystem.out.println(config.getStorageMode());//存储模式 MODE_DISK 磁盘存储模式System.out.println(config.getSyncMode());//同步模式 nullSystem.out.println(config.getEncryptKey());//密钥 null 默认是开放的,不加密的

自定义数据库配置

知道数据库基本设置的七种属性之后,那么就可以通过Builder的内部方法进行设置,先通过一段自定义数据库配置项创建数据库的代码来进行查看。

StoreConfig.Builder builder = new StoreConfig.Builder();builder.setName("DemoSql.db");builder.setReadOnly(false);builder.setSyncMode(null);builder.setJournalMode(StoreConfig.JournalMode.MODE_WAL);builder.setStorageMode(StoreConfig.StorageMode.MODE_DISK);builder.setDatabaseFileType(DatabaseFileType.NORMAL);String key = "123456";builder.setEncryptKey(key.getBytes());StoreConfig config = builder.build();RdbStore rdbStore = helper.getRdbStore(config, 1,callback , null);

使用以上配置项就可以对数据库进行之定义配置,这里解释以下每个数据项分别代表什么意思,以及要传入对应的参数是什么。

builder.setName("DemoSql.db");

设置数据库名称, .db作为文件后缀。

builder.setReadOnly(false);

设置数据库是否只读,设置之后数据库只能读取不能增加和修改,一般设置false。

builder.setSyncMode(null);

设置数据库同步模式,同步模式一般用于多应用分布式开发多节点访问数据库,将某一个节点的数据同步给另外的节点,参数类型是StoreConfig下的SyncMode枚举。

  1. MODE_OFF 关闭同步(默认)
  2. MODE_NORMAL 正常同步
  3. MODE_FULL 完全同步 (将所有的东西复制一份给另外的节点)
  4. MODE_EXTRA 额外同步,增量同步 (将新增的数据复制给另外的节点)
builder.setJournalMode(StoreConfig.JournalMode.MODE_WAL);

设置数据库日志模式,数据库在创建的时候会生成一个日志,这个日志会伴随着数据库操作事务的开启和关闭相应的生成和删除,参数StoreConfig下的JournalMode枚举。

  1. MODE_DELETE 删除日志 sqlite默认删除模式,一般在事务开启的时候会创建一个回滚日志,创建一个临时文件里面,新增(修改)的数据会放在临时文件里面,等事务提交了,在把数据存放到主文件里面,并删除回滚日志
  2. MODE_TRUNCATE 截取模式
  3. MODE_PERSIST 持久模式 事务结束不删除回滚日志,新增(修改)数据的时候会在回滚日志的0索引位置头部覆写,这样同样可以达到删除回滚日志的效果,并且减少了反复删除磁盘文件的磁盘开销
  4. MODE_MEMORY 内存模式 将日志写在内存文件里面,而不是存放在磁盘里面,由于磁盘中没有可用于恢复的数据,如果事务发生崩溃或者错误,内存中的数据就会丢失;内存中的好处是读写比磁盘快
  5. MODE_WAL wal模式也可称为预写日志模式,当数据库首次连接的时候wal文件被创建,当最后一个数据库连接被关闭的时候,删除wal文件;如果最后一次数据库连接没有正常关闭,wal文件被保存下来,直到下一次打开数据库才会被删除;使用wal模式会生成一个shm共享内存文件,用于提供一块共享内存给多个wal模式中访问相同的数据库,这也是鸿蒙数据库的默认模式。
  6. MODE_OFF 关闭日志 数据直接写到主文件里面,没有日志 ,静止SQLite原子提交和回滚功能;只能查不能写,因为禁止提交了。
builder.setStorageMode(StoreConfig.StorageMode.MODE_DISK);

设置数据库文件的存储位置,分为磁盘和内存,参数类型是StoreConfig下的StorageMode枚举。

  1. MODE_MEMORY 内存模式 数据库会存储在内存中,在磁盘中看不见,事务发生崩溃之后数据不可再生。
  2. MODE_DISK 磁盘模式(默认) 数据库会以文件的模式放在磁盘上,只要磁盘上的数据库文件还在就可以再生数据,鸿蒙数据库存储的默认模式。
builder.setDatabaseFileType(DatabaseFileType.NORMAL);

设置数据库文件类型,参数类型是DatabaseFileType枚举。

  1. NORMAL 正常数据库文件 (默认)
  2. BACKUP 备份数据库文件
  3. CORRUPT 数据库文件是损坏的
builder.setEncryptKey(key.getBytes());

设置数据库密钥,相当于给数据库设置了一个密码,在打开数据库的时候需要使用相同密码才能打开,参数类型是一个字节数据byte[] encryptKey。

以上操作就可以一定义数据库配置项了。

打开加密的关系型数据库

在打开加密的关系型数据库的时候要保证setEncryptKey(key.getBytes())的密钥一致,不然会抛出file is not a database的异常,具体打开方法如下:

private void openDB(){   String key = "123456";   StoreConfig.Builder builder = new StoreConfig.Builder()  .setName("DemoSql.db")  .setReadOnly(false)  .setSyncMode(null)  .setJournalMode(StoreConfig.JournalMode.MODE_WAL)  .setStorageMode(StoreConfig.StorageMode.MODE_DISK)  .setDatabaseFileType(DatabaseFileType.NORMAL)  .setEncryptKey(key.getBytes());   StoreConfig config = builder.build();   DatabaseHelper helper = new DatabaseHelper(this);   RdbStore rdbStore = helper.getRdbStore(config,1,openCallback,null);}

这里有一点需要注意,这个opencallback是新创建的一个RdbOpenCallback回调函数,并且onCreate回调方法里面不写创建数据表的操作。

private static final RdbOpenCallback openCallback = new RdbOpenCallback() {    @Override    public void onCreate(RdbStore rdbStore) {//创建数据库的时候表已经存在勒,那么打开的时候就不需要再进行创建了    }    @Override    public void onUpgrade(RdbStore rdbStore, int i, int i1) {    }};

关系型数据库的增删改查

关系型数据库是在SQLite基础上实现的本地数据操作机制,HarmonyOS对SQlite数据的封装,使得关系型数据库的增删改查可以不用编写SQL语句直接调用接口实现增删改查的功能,同样也支持原生SQL语句操作。

关系型数据库提供以下接口:

  • 数据库的创建和删除
    在这里插入图片描述
    builder()内部类,对数据库进行配置。
    onCreate()方法,数据库被创建时回调。
    onUpgrade()方法,数据库升级被回调。
    getRdbStore()方法,根据配置创建或打开数据库。
    deleteRdbStore()方法,删除指定数据库。

  • 数据库的加密
    HarmonyOS数据库之关系型数据库
    给数据库添加加密密钥。

  • 增删改查
    新增:在这里插入图片描述
    更新:
    在这里插入图片描述
    删除:
    在这里插入图片描述
    查询:
    在这里插入图片描述

  • 数据库谓词的查询
    关系型数据库提供了用于设置数据库操作条件的谓词AbsRdbPredicates,其中包括两个实现子类RdbPredicates和RawRdbPredicates:
    RdbPredicates:开发者无需编写复杂的SQL语句,仅通过调用该类中条件相关的方法,如equalTo、notEqualTo、groupBy、orderByAsc、beginsWith等,就可自动完成SQL语句拼接,方便用户聚焦业务操作。
    RawRdbPredicates:可满足复杂SQL语句的场景,支持开发者自己设置where条件子句和whereArgs参数。不支持equalTo等条件接口的使用。
    在这里插入图片描述

  • 查询结果集
    关系型数据库提供了查询返回的结果集ResultSet,他指向查询结果中的一行数据,供用户对查询结果进行遍历和访问。ResultSet的对外API如下表格。
    在这里插入图片描述
    在这里插入图片描述

  • 事务
    关系型数据库提供事务机制,来保证用户操作的原子性。对单条数据进行数据库操作时,无需开启事务;插入大量数据时,开启事务可以保证数据的准确性。如果中途操作出现失败,会执行回滚操作。
    在这里插入图片描述

  • 事务和结果集观察者
    关系型数据库提供了事务和结果集观察者能力,当对应的事件被触发时,观察者会收到通知。
    在这里插入图片描述

  • 数据库的备份和恢复
    用户可以将当前数据库的数据进行保存进行备份,还可以在需要的时候进行数据恢复。
    在这里插入图片描述
    restore和backup方法传入的值不一样备份以及恢复的数据也不一样,主要是在于加密和非加密之间的区别。

创建数据库

创建数据库首先要添加数据库配置StoreConfig,然后通过工具类DatabaseHelper的getRdbStore方法获取数据库对象进行创建。

  • 添加数据库配置(这里只指定了数据库名字,其他都是默认)
//先要准备数据库的配置信息,这里只配置数据库名字,其他为默认值StoreConfig config = StoreConfig.newDefaultConfig("DemoSql.db");//后缀db
  • 获取DatabaseHelper 实例对象
DatabaseHelper helper = new DatabaseHelper(this);
  • 通过helper.getRdbStore()方法创建数据库
RdbStore store = helper.getRdbStore(config, 1, callback, ResultSetHook);

创建数据库的代码很简单,到这里就创建好了一个默认配置的数据库;具体参数解释一下:

  • config 数据库配置
  • 1 数据库版本号
  • callback RdbOpenCallback回调方法
  • ResultSetHook 结果集Hook回调方法

RdbOpenCallback回调有一系列方法,这里也做一下简单的说明:

private static final RdbOpenCallback callback =  new RdbOpenCallback() {    @Override    public void onCreate(RdbStore rdbStore) { //onCreate 创建数据库会回调的方法 //rdbStore 创建好的数据库 //创建数据表 //IF NOT EXISTS 如果表不存在则创建 //表名 test //(括号里面是字段) //id integer类型  PRIMARY KEY主键  AUTOINCREMENT自增 //name TEXT文本类型 NOT NULL不能为空 //age INTEGER类型 NOT NULL不能为空 //salary REAL小数 rdbStore.executeSql("CREATE TABLE IF NOT EXISTS " +      "test(id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,age INTEGER NOT NULL,salary REAL)");   }   @Override   public void onUpgrade(RdbStore rdbStore, int i, int i1) {//数据库升级时会回调   }   @Override   public void onDowngrade(RdbStore store, int currentVersion, int targetVersion) {super.onDowngrade(store, currentVersion, targetVersion);//数据库降级时会回调   }   @Override   public void onOpen(RdbStore store) {super.onOpen(store);//数据库被打开时回调   }   @Override   public void onCorruption(File databaseFile) {super.onCorruption(databaseFile);//数据库出现问题会回调   }};
  1. onCreate() 数据库被创建时回调,并返回创建好的数据库,一般也在oncreate方法里面做一些初始化数据表的操作
  2. onUpgrade() 数据库版本升级时回调
  3. onDowngrade() 数据库版本降级时回调
  4. onOpen() 数据库被打开时回调
  5. onCorruption() 数据库发生错误时回调

新增数据

调用数据库的insert方法进行插入数据,返回的是当前新数据所在的行号,如果是-1则返回失败。

先要创建一个ValuesBucket实例对象,并设置对应字段的值,注意类型不能搞错:

ValuesBucket valuesBucket = new ValuesBucket();valuesBucket.putInteger("id",1);valuesBucket.putString("name","张三");valuesBucket.putInteger("age",20);valuesBucket.putDouble("salary",9000.12);

然后通过insert方法进行插入:

//test表名//valuesBucket实例对象long insert = rdbStore.insert("test",valuesBucket);//如果返回的insert不是-1,则说明插入成功。HiLog.error(hiLogLabel,""+insert);

额外说一点,每一次插入数据都要实例化一个ValuesBucket实力对象,如果是一次性插入多条数据,就可以通过for循环来实现。

通过控制台输出的值可以判断数据是否插入成功,这里输出1说明插入成功。
HarmonyOS数据库之关系型数据库

查询数据

查询数据库有两种方式,第一种是通过谓词拼接的形式查询数据,第二种是通过原生的SQL语句查询数据。

1.rdbStore.query() 谓词拼接的形式查询数据

谓词查询有RdbPredicates和RawRdbPredicates两种,RdbPredicates可以满足某些值等于,不等于,最小值最大值在某个区间等等的查询方法,RawRdbPredicates可满足复杂SQL语句的场景,支持开发者自己设置where条件子句和whereArgs参数,但是RawRdbPredicates不支持RdbPredicates条件接口的调用。

查询步骤:

先创建实例对象:

//test数据库表名RdbPredicates test = new RdbPredicates("test");

设置查询条件:

//某个值等于value的数据 这里是年龄等于20的数据test.equalTo("age",20);//排序模式 让查询出来的数据组照key字段的大小降序排列test.orderByDesc("salary");

设置结果集:

//返回的数据字段都装在一个结果集里面String[] columns = new String[]{"id","name","age","salary"};

通过query方法查询拿到结果集:

ResultSet query = rdbStore.query(test, columns);

循环输出结果集里面的值,看看是否符合我们的预期条件:

for (int i = 0;i<query.getRowCount();i++){    query.goToRow(i);//让指针指向第几行    int id = query.getInt(query.getColumnIndexForName("id"));//拿到列索引,通过列的名字去拿    String name = query.getString(query.getColumnIndexForName("name"));    int age = query.getInt(query.getColumnIndexForName("age"));    double salary = query.getDouble(query.getColumnIndexForName("salary"));    HiLog.error(hiLogLabel,"id:"+id + " name:" + name + " age:" + age + " salary:" + salary);}

HarmonyOS数据库之关系型数据库

2.rdbStore.querySql() 原生SQL语句查询数据

原生SQL语句查询数据调用querySql()方法,参数一是查询的sql语句,参数二是语句里面问号的值。

比如这里的条件是age=?,那么在后面的String[]{“20”}里面就对应age=20。

ResultSet resultSet = rdbStore.querySql("select id,name,age," +"salary from test where age=? order by salary desc", new String[]{"20"});

更新数据

更新数据要使用到rdbStore.update()方法,第一个参数是一个ValuesBucket对象,就是我们要把数据修改成什么样子,第二个数据是谓词RdbPredicates指向我们要修改什么数据;那么这里的例子是我们要修改id是1的这条数据,名字改成王五,年龄改成30。

1.谓词修改数据

首先构建修改条件:

RdbPredicates rdbPredicates = new RdbPredicates("test");rdbPredicates.equalTo("id",1);

然后构建修改参数值:

ValuesBucket valuesBucket1 = new ValuesBucket();valuesBucket1.putString("name","王五");valuesBucket1.putInteger("age",30);

最后调用update方法进行修改:

int update = rdbStore.update(valuesBucket1, rdbPredicates);

2.原生SQL修改数据

通过数据库的executeSql()执行sql语句进行修改。

rdbStore.executeSql("update test set name='王五' where id=?",new Object[]{1});

删除数据

调用delete()方法的时候只需要传入符合条件的谓词就行了,返回的是删除影响的当前行数,如果失败返回0。

1.谓词查询

RdbPredicates deleteRDB = new RdbPredicates("test");deleteRDB.equalTo("age",20);int delete = rdbStore.delete(deleteRDB);

2.原生SQL查询

int delete = rdbStore.executeSql("delete from test where age=?",new Object[]{20});

以上就是数据库的增删改查基本操作。

关系型数据库的基本操作到这里就结束了~