鸿蒙关系型数据库操作实践尝试

数据库
关系型数据库提供了插入数据的接口,通过ValuesBucket输入要存储的数据,通过返回值判断是否插入成功,插入成功时返回最新插入数据所在的行号,失败则返回-1。

[[413806]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

简单使用

1. 创建数据库

初始化数据库

  1. public class HiDbHelper { 
  2.  
  3.     //1. 配置数据库相关信息 
  4.     private static StoreConfig config = StoreConfig.newDefaultConfig("RdbStoreTest.db"); 
  5.  
  6.     //RdbOpenCallback用于管理数据库的创建、升级和降级 
  7.     private static RdbOpenCallback callback = new RdbOpenCallback() { 
  8.         @Override 
  9.         public void onCreate(RdbStore rdbStore) { 
  10.             //该方法当数据库不存在时会被调用 
  11.             //2. 初始化数据库表 
  12.             rdbStore.executeSql("CREATE TABLE IF NOT EXISTS employee (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); 
  13.         } 
  14.  
  15.         @Override 
  16.         public void onUpgrade(RdbStore rdbStore, int i, int i1) { 
  17.  
  18.         } 
  19.     }; 
  20.  
  21.     //RdbStore是一个接口,提供了对数据库进行增删改查等操作 
  22.     private static volatile RdbStore store; 
  23.  
  24.     //3. 获取对数据库操作的对象 
  25.     public static RdbStore singleStore() { 
  26.         synchronized (HiDbHelper.class) { 
  27.             if (store == null) { 
  28.                 synchronized (HiDbHelper.class) { 
  29.                     //DatabaseHelper提供了多种模式来操作数据库,主要是对ORM(Object Relational Mapping),RDB(Relational Database),Preferences这三类数据库的构建和删除 
  30.                     DatabaseHelper helper = new DatabaseHelper(MyApplication.appContext); 
  31.                     //通过getRdbStore获取关系型数据库对象 
  32.                     //getRdbStore四个参数分别是: 
  33.                     //StoreConfig config: 对数据库的配置,包括数据库路径,存储模式,是否为只读等 
  34.                     //int version: 数据库版本,主要用于指示数据库的升级或降级 
  35.                     //RdbOpenCallback openCallback: 用于管理数据库的创建、升级和降级 
  36.                     //ResultSetHook resultSetHook: 这个类允许用户自定义结果集 
  37.                     store = helper.getRdbStore(config, 1, callback, null); 
  38.                 } 
  39.             } 
  40.         } 
  41.         return store; 
  42.     } 

2. 插入数据

关系型数据库提供了插入数据的接口,通过ValuesBucket输入要存储的数据,通过返回值判断是否插入成功,插入成功时返回最新插入数据所在的行号,失败则返回-1。

  1. //1. 构建需要插入的数据,关系型数据库中,插入的数据是以ValuesBucket形式存储的 
  2. ValuesBucket values = new ValuesBucket(); 
  3. values.putInteger("id", 1); 
  4. values.putString("name""zhangsan"); 
  5. values.putInteger("age", 18); 
  6. values.putDouble("salary", 100.5); 
  7. values.putByteArray("blobType", new byte[] {1, 2, 3}); 
  8. //2. 执行插入操作,第一个参数为数据需要插入的表名,第二个参数为需要插入的数据 
  9. long id = HiDbHelper.singleStore().insert("employee"values); 

3. 查询数据

查询操作

关系型数据库查询提供类两种查询方式:

1.通过调用ResultSet query(AbsRdbPredicates predicates, String[] columns)查询,该方法将包含查询条件的谓词自动拼接成完整的SQL语句进行查询操作,无需调用者传入原生的SQL

传入参数说明

  • AbsRdbPredicates predicates:谓词,可设置查询条件。AbsRdbPredicates的实现类有两个:RdbPredicates和RawRdbPredicates
  • RdbPredicates:支持调用谓词提供的equalTo等接口,设置查询条件。
  • RawRdbPredicates:仅支持设置表名、where条件子句、whereArgs三个参数,不支持equalTo等接口调用。
  • columns:规定查询返回的列。

关于更多谓词的使用可以查询官方文档关系型数据库开发指导

  1. //1. 需要查询的列 
  2. String[] columns = new String[] {"id""name""age""salary"}; 
  3. //2. 构建查询条件 
  4. RdbPredicates rdbPredicates = new RdbPredicates("employee").equalTo("age", 23).orderByAsc("salary"); 
  5. //3. 查询获取结果集 
  6. ResultSet resultSet = HiDbHelper.singleStore().query(rdbPredicates, columns); 

通过调用ResultSet querySql(String sql, String[] sqlArgs)使用原生SQL语句进行查询

参数说明:

  • String sql:原生用于查询的sql语句
  • String[] sqlArgs:sql语句中占位符参数的值,若select语句中没有使用占位符,该参数可以设置为null。
  1. String sql = "select id,name,age,salary from employee where age = 23"
  2. ResultSet resultSet = HiDbHelper.singleStore().querySql(sql, null); 

结果集处理

当调用查询方法获取到ResultSet时,其默认并没有指向当前结果集中的数据,如果此时调用其String getString(int columnIndex)获取当前行指定索列的值,则会抛出异常

  1. ohos.data.resultset.ResultSetIndexOutOfRangeException: checkState :row index is illegal. 

正确的操作应该是:

先调用boolean goToNextRow()将结果集向后移动一行,返回true这表示当前位置有数据,再对结果进行处理,如果要获取ResultSet更多使用方式,可以查看官方文档

  1. if (resultSet.goToNextRow()) { 
  2.     HiLog.debug(TAG, "select name is %{public}s", resultSet.getString(1)); 

4. 更新数据

调用更新接口,传入要更新的数据,并通过AbsRdbPredicates指定更新条件。该接口的返回值表示更新操作影响的行数。如果更新失败,则返回0。

  1. //1. 构建需要更新的数据的条件 
  2. RdbPredicates rdbPredicates = new RdbPredicates("employee"
  3.                         .equalTo("id",1); 
  4. //2. 构建需要更新的数据 
  5. ValuesBucket values = new ValuesBucket(); 
  6. values.putString("name","Mo"); 
  7. //3. 执行更新操作 
  8. HiDbHelper.singleStore().update(values, rdbPredicates); 

5. 删除数据

调用删除接口,通过AbsRdbPredicates指定删除条件。该接口的返回值表示删除的数据行数,可根据此值判断是否删除成功。如果删除失败,则返回0。

  1. //1. 构建需要删除数据的条件 
  2. RdbPredicates rdbPredicates = new RdbPredicates("test"
  3.                         .equalTo("id", 1); 
  4. //2. 执行删除操作 
  5. HiDbHelper.singleStore().delete(rdbPredicates); 

事务

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

事务的API一共有三个

beginTransaction():开启事务。

markAsCommit():设置事务的标记为成功。

endTransaction():结束事务。

其中markAsCommit()和endTransaction()必须与beginTransaction(),如果单独调用,则会抛出异常

markAsCommit()与endTransaction()不能独立调用

如果单独调用markAsCommit()

则会抛出异常

  1. java.util.EmptyStackException 

如果单独调用endTransaction()

则会抛出异常

  1. java.lang.IllegalStateException: Cannot do the transaction operation, because there is no current transaction

如果在事务块中如果调用了markAsCommit(),本次批量操作数据出现错误,则不会进行回滚操作,该方法可以用于某些情况下阻止回滚

示例代码

  1. ValuesBucket values = new ValuesBucket(); 
  2. values.putInteger("id", 1); 
  3. values.putString("name""zhangsan"); 
  4. values.putInteger("age", 18); 
  5. values.putDouble("salary", 100.5); 
  6. values.putByteArray("blobType", new byte[] {1, 2, 3}); 
  7.  
  8. //开启事务 
  9. HiDbHelper.singleStore().beginTransaction(); 
  10. //插入两条id相同的数据 
  11. long id1 = HiDbHelper.singleStore().insert("employee"values); 
  12. long id2 = HiDbHelper.singleStore().insert("employee"values); 
  13. //加入下列的判断,即使id2插入不成功,本次事务也不会进行回滚 
  14. //if(id1 == 1) { 
  15. //  HiDbHelper.singleStore().markAsCommit(); 
  16. //} 
  17. //结束事务 
  18. HiDbHelper.singleStore().endTransaction(); 

开启事务除使用beginTransaction()外,还可以使用beginTransactionWithObserver(TransactionObserver transactionObserver),在开启事务的同时注册观察者,用于监听事务的开启,提交,回滚操作。

注意:在开启事务后,一定记得在适当的时机进行关闭操作,否则在对数据库进行备份等操作时会抛出异常

  1. java.lang.IllegalArgumentException: The rdb is in transaction

为了代码的健壮性,可以在对数据库进行备份等操作前调用RdbStore的isInTransaction判断当前是否有事务还没有关闭,如果没有关闭,则进行关闭操作

数据库升级,降级,备份,删除,恢复

作为一名老移动端开发者,由于最近事务繁忙,这部分功能暂时没有有效的验证,有玩过的朋友欢迎进行进一步的分享。也可以期待后续我的帖子。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2018-07-18 09:16:39

关系型非关系型数据库

2021-09-06 10:24:12

鸿蒙HarmonyOS应用

2020-12-29 11:26:22

鸿蒙HarmonyOS数据库

2010-12-10 10:17:21

关系型数据库

2022-06-13 08:30:01

数据库管理系统

2017-03-17 14:44:04

关系型数据库原理

2009-08-24 16:46:04

C# 泛型

2023-05-22 16:10:51

动态共享包数据库

2022-12-27 08:38:45

关系型数据库设计

2016-08-23 14:25:19

MySQL约束数据库

2022-07-27 08:32:01

数据库MySQL

2021-01-26 13:31:48

数据库关系型数据库冗余

2023-05-20 08:11:55

2013-04-26 16:18:29

大数据全球技术峰会

2018-03-26 12:58:52

数据库OracleMySQL

2013-06-28 11:28:21

Facebook数据库大数据

2011-04-13 16:13:53

云计算关系型数据库

2013-01-08 14:24:23

2017-01-04 16:18:05

非数据库NoSql关系型数据库

2011-06-07 17:14:15

关系型数据库压缩技术
点赞
收藏

51CTO技术栈公众号