简单使用
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. 查询数据
查询操作
关系型数据库查询提供类两种查询方式:
通过调用ResultSet query(AbsRdbPredicates predicates, String[] columns)查询,该方法将包含查询条件的谓词自动拼接成完整的SQL语句进行查询操作,无需调用者传入原生的SQL
传入参数说明
- AbsRdbPredicates predicates:谓词,可设置查询条件。AbsRdbPredicates的实现类有两个:RdbPredicates和RawRdbPredicates
- RdbPredicates:支持调用谓词提供的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判断当前是否有事务还没有关闭,如果没有关闭,则进行关闭操作
数据库升级,降级,备份,删除,恢复
作为一名老移动端开发者,由于最近事务繁忙,这部分功能暂时没有有效的验证,有玩过的朋友欢迎进行进一步的分享。也可以期待后续我的帖子。