麒麟v10 上部署 TiDB v5.1.2 生产环境优化实践
763
2023-06-01
鸿蒙关系型数据库操作实践尝试
想了解更多内容,请访问:
和***官方合作共建的鸿蒙技术社区
简单使用
1. 创建数据库
初始化数据库
public class HiDbHelper { //1. 配置数据库相关信息 private static StoreConfig config = StoreConfig.newDefaultConfig("RdbStoreTest.db"); //RdbOpenCallback用于管理数据库的创建、升级和降级 private static RdbOpenCallback callback = new RdbOpenCallback() { @Override public void onCreate(RdbStore rdbStore) { //该方法当数据库不存在时会被调用 //2. 初始化数据库表 rdbStore.executeSql("CREATE TABLE IF NOT EXISTS employee (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); } @Override public void onUpgrade(RdbStore rdbStore, int i, int i1) { } }; //RdbStore是一个接口,提供了对数据库进行增删改查等操作 private static volatile RdbStore store; //3. 获取对数据库操作的对象 public static RdbStore singleStore() { synchronized (HiDbHelper.class) { if (store == null) { synchronized (HiDbHelper.class) { //DatabaseHelper提供了多种模式来操作数据库,主要是对ORM(Object Relational Mapping),RDB(Relational Database),Preferences这三类数据库的构建和删除 DatabaseHelper helper = new DatabaseHelper(MyApplication.appContext); //通过getRdbStore获取关系型数据库对象 //getRdbStore四个参数分别是: //StoreConfig config: 对数据库的配置,包括数据库路径,存储模式,是否为只读等 //int version: 数据库版本,主要用于指示数据库的升级或降级 //RdbOpenCallback openCallback: 用于管理数据库的创建、升级和降级 //ResultSetHook resultSetHook: 这个类允许用户自定义结果集 store = helper.getRdbStore(config, 1, callback, null); } } } return store; } }
2. 插入数据
关系型数据库提供了插入数据的接口,通过ValuesBucket输入要存储的数据,通过返回值判断是否插入成功,插入成功时返回最新插入数据所在的行号,失败则返回-1。
//1. 构建需要插入的数据,关系型数据库中,插入的数据是以ValuesBucket形式存储的 ValuesBucket values = new ValuesBucket(); values.putInteger("id", 1); values.putString("name", "zhangsan"); values.putInteger("age", 18); values.putDouble("salary", 100.5); values.putByteArray("blobType", new byte[] {1, 2, 3}); //2. 执行插入操作,第一个参数为数据需要插入的表名,第二个参数为需要插入的数据 long id = HiDbHelper.singleStore().insert("employee", values);
3. 查询数据
查询操作
关系型数据库查询提供类两种查询方式:
1.通过调用ResultSet query(AbsRdbPredicates predicates, String[] columns)查询,该方法将包含查询条件的谓词自动拼接成完整的SQL语句进行查询操作,无需调用者传入原生的SQL
传入参数说明
AbsRdbPredicates predicates:谓词,可设置查询条件。AbsRdbPredicates的实现类有两个:RdbPredicates和RawRdbPredicatesRdbPredicates:支持调用谓词提供的equalTo等接口,设置查询条件。RawRdbPredicates:仅支持设置表名、where条件子句、whereArgs三个参数,不支持equalTo等接口调用。columns:规定查询返回的列。
关于更多谓词的使用可以查询官方文档关系型数据库开发指导
//1. 需要查询的列 String[] columns = new String[] {"id", "name", "age", "salary"}; //2. 构建查询条件 RdbPredicates rdbPredicates = new RdbPredicates("employee").equalTo("age", 23).orderByAsc("salary"); //3. 查询获取结果集 ResultSet resultSet = HiDbHelper.singleStore().query(rdbPredicates, columns);
通过调用ResultSet querySql(String sql, String[] sqlArgs)使用原生SQL语句进行查询
参数说明:
String sql:原生用于查询的sql语句String[] sqlArgs:sql语句中占位符参数的值,若select语句中没有使用占位符,该参数可以设置为null。
String sql = "select id,name,age,salary from employee where age = 23"; ResultSet resultSet = HiDbHelper.singleStore().querySql(sql, null);
结果集处理
当调用查询方法获取到ResultSet时,其默认并没有指向当前结果集中的数据,如果此时调用其String getString(int columnIndex)获取当前行指定索列的值,则会抛出异常
ohos.data.resultset.ResultSetIndexOutOfRangeException: checkState :row index is illegal.
正确的操作应该是:
先调用boolean goToNextRow()将结果集向后移动一行,返回true这表示当前位置有数据,再对结果进行处理,如果要获取ResultSet更多使用方式,可以查看官方文档
if (resultSet.goToNextRow()) { HiLog.debug(TAG, "select name is %{public}s", resultSet.getString(1)); }
4. 更新数据
调用更新接口,传入要更新的数据,并通过AbsRdbPredicates指定更新条件。该接口的返回值表示更新操作影响的行数。如果更新失败,则返回0。
//1. 构建需要更新的数据的条件 RdbPredicates rdbPredicates = new RdbPredicates("employee") .equalTo("id",1); //2. 构建需要更新的数据 ValuesBucket values = new ValuesBucket(); values.putString("name","Mo"); //3. 执行更新操作 HiDbHelper.singleStore().update(values, rdbPredicates);
5. 删除数据
调用删除接口,通过AbsRdbPredicates指定删除条件。该接口的返回值表示删除的数据行数,可根据此值判断是否删除成功。如果删除失败,则返回0。
//1. 构建需要删除数据的条件 RdbPredicates rdbPredicates = new RdbPredicates("test") .equalTo("id", 1); //2. 执行删除操作 HiDbHelper.singleStore().delete(rdbPredicates);
事务
关系型数据库提供事务机制,来保证用户操作的原子性。对单条数据进行数据库操作时,无需开启事务;插入大量数据时,开启事务可以保证数据的准确性。如果中途操作出现失败,会执行回滚操作。
事务的API一共有三个
beginTransaction():开启事务。
markAsCommit():设置事务的标记为成功。
endTransaction():结束事务。
其中markAsCommit()和endTransaction()必须与beginTransaction(),如果单独调用,则会抛出异常
markAsCommit()与endTransaction()不能独立调用
如果单独调用markAsCommit()
则会抛出异常
java.util.EmptyStackException
如果单独调用endTransaction()
则会抛出异常
java.lang.IllegalStateException: Cannot do the transaction operation, because there is no current transaction.
如果在事务块中如果调用了markAsCommit(),本次批量操作数据出现错误,则不会进行回滚操作,该方法可以用于某些情况下阻止回滚
示例代码
ValuesBucket values = new ValuesBucket(); values.putInteger("id", 1); values.putString("name", "zhangsan"); values.putInteger("age", 18); values.putDouble("salary", 100.5); values.putByteArray("blobType", new byte[] {1, 2, 3}); //开启事务 HiDbHelper.singleStore().beginTransaction(); //插入两条id相同的数据 long id1 = HiDbHelper.singleStore().insert("employee", values); long id2 = HiDbHelper.singleStore().insert("employee", values); //加入下列的判断,即使id2插入不成功,本次事务也不会进行回滚 //if(id1 == 1) { // HiDbHelper.singleStore().markAsCommit(); //} //结束事务 HiDbHelper.singleStore().endTransaction();
开启事务除使用beginTransaction()外,还可以使用beginTransactionWithObserver(TransactionObserver transactionObserver),在开启事务的同时注册观察者,用于监听事务的开启,提交,回滚操作。
注意:在开启事务后,一定记得在适当的时机进行关闭操作,否则在对数据库进行备份等操作时会抛出异常
java.lang.IllegalArgumentException: The rdb is in transaction.
为了代码的健壮性,可以在对数据库进行备份等操作前调用RdbStore的isInTransaction判断当前是否有事务还没有关闭,如果没有关闭,则进行关闭操作
数据库升级,降级,备份,删除,恢复
作为一名老移动端开发者,由于最近事务繁忙,这部分功能暂时没有有效的验证,有玩过的朋友欢迎进行进一步的分享。也可以期待后续我的帖子。
想了解更多内容,请访问:
和***官方合作共建的鸿蒙技术社区
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。