为ContentProvider添加数据库事务支持

简介:

介绍:数据库事务是由一组数据库操作序列组成,事务作为一个整体被执行。

事务的原子性:包含在其中的对数据库的操作序列最终要么全部执行,要么全部不执行。当全部执行时,事务对数据库的修改将生效;当全部不执行时,数据库维持原有的状态,不会被修改。

问题:最近在做一个从sdcard导入数据到数据库的功能,当导入失败时,数据库要恢复到导入前的状态。使用数据库事务处理能很好地满足到我们的需求。

我们知道Android平台上使用的sqlite数据库是支持事务处理功能的,实现的代码如下:

  1. SQLiteDatabase db =mOpenHelper.getWritableDatabase();  
  2.                    db.beginTransaction();//开始事务  
  3. //进行insertdelete update等数据库操作  
  4. db.setTransactionSuccessful();//设置事务标记为Successful  
  5. db.endTransaction();//提交事务  

可是,对于已经封装成ContentProvider的Sqlite我们应该如何让其支持事务处理功能呢?

解决办法:查看ContentProvider的API说明文档,我们惊喜地发现applyBatch(String authority,ArrayList<ContentProviderOperation> operations)这个方法,难道只需要直接使用这个方法就可以实现事务了?

谨慎起见我们先来看看ContentProvider的源码,最后追踪到这个方法:

  1. public ContentProviderResult[]applyBatch(ArrayList<ContentProviderOperation> operations)  
  2.             throwsOperationApplicationException {  
  3.        final int numOperations = operations.size();  
  4.        final ContentProviderResult[] results = newContentProviderResult[numOperations];  
  5.        for (int i = 0; i < numOperations; i++) {//遍历数据库操作序列  
  6.             results[i] =operations.get(i).apply(this, results, i);//执行数据库操作  
  7.        }  
  8.        return results;//返回结果  
  9.    }  


从上面的代码中,我们找不到和db.beginTransaction()、db.endTransaction()相似的方法,也就是说,这个方法只是进行简单的批处理,并没有保障这些数据库操作的原子性。

好吧。我们稍微动下脑筋,覆写ContentProvider的applyBatch()方法,为其添加事务处理功能。代码如下:

  1. @Override  
  2. publicContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation>operations)  
  3.             throwsOperationApplicationException{  
  4.           SQLiteDatabasedb = mOpenHelper.getWritableDatabase();  
  5.           db.beginTransaction();//开始事务  
  6.           try{  
  7.                    ContentProviderResult[]results = super.applyBatch(operations);  
  8.                    db.setTransactionSuccessful();//设置事务标记为successful  
  9.                    returnresults;  
  10.           }finally {  
  11.                    db.endTransaction();//结束事务  
  12.           }  
  13. }  


然后,我们该如何使用这个applyBatch()方法呢?applyBatch()的第一个参数实现事务的Provider的authority属性,第二个参数是数据库操作序列,构建数据库操作的对象使用了builder设计模式,下面是一个使用applyBatch()的例子:

  1. ArrayList<ContentProviderOperation>ops = new ArrayList<ContentProviderOperation>();  
  2. ops.add(ContentProviderOperation.newDelete(Person.CONTENT_URI).build());//添加一个删除Person表的操作  
  3. ops.add(ContentProviderOperation.newInsert(Home.CONTENT_URI).withValues(values).build());//添加一条记录到Home表  
  4. getContentResolver().applyBatch(PROVIDER.AUTHORITY,ops);//处理事务  

总结:

1、sqlite支持事务处理操作

2、对于封装成ContentProvider的sqlite数据库,我们可以通过覆写ContentProvider的applyBatch(Stringauthority, ArrayList<ContentProviderOperation> operations)方法来实现对事务处理的支持


目录
相关文章
|
3月前
|
SQL 关系型数据库 MySQL
乐观锁在分布式数据库中如何与事务隔离级别结合使用
乐观锁在分布式数据库中如何与事务隔离级别结合使用
|
21天前
|
SQL 关系型数据库 MySQL
乐观锁在分布式数据库中如何与事务隔离级别结合使用
乐观锁在分布式数据库中如何与事务隔离级别结合使用
|
3月前
|
SQL 数据库 数据安全/隐私保护
SQL Server数据库Owner导致事务复制log reader job无法启动的解决办法
【8月更文挑战第14天】解决SQL Server事务复制Log Reader作业因数据库所有者问题无法启动的方法:首先验证数据库所有者是否有效并具足够权限;若非,使用`ALTER AUTHORIZATION`更改为有效登录名。其次,确认Log Reader使用的登录名拥有读取事务日志所需的角色权限。还需检查复制配置是否准确无误,并验证Log Reader代理的连接信息及参数。重启SQL Server Agent服务或手动启动Log Reader作业亦可能解决问题。最后,审查SQL Server错误日志及Windows事件查看器以获取更多线索。
|
14天前
|
数据库
什么是数据库的事务隔离级别,有什么作用
【10月更文挑战第21】什么是数据库的事务隔离级别,有什么作用
12 3
|
14天前
|
存储 关系型数据库 数据挖掘
什么是数据库的事务隔离级别
【10月更文挑战第21】什么是数据库的事务隔离级别
11 1
|
20天前
|
存储 数据库 数据库管理
数据库事务安全性控制如何实现呢
【10月更文挑战第15天】数据库事务安全性控制如何实现呢
|
20天前
|
存储 数据库 数据库管理
什么是数据库事务安全性控制
【10月更文挑战第15天】什么是数据库事务安全性控制
|
20天前
|
供应链 数据库
数据库事务安全性控制有什么应用场景吗
【10月更文挑战第15天】数据库事务安全性控制有什么应用场景吗
|
20天前
|
存储 关系型数据库 MySQL
数据库的事务控制
【10月更文挑战第15天】数据库的事务控制
18 2
|
5月前
|
存储 关系型数据库 MySQL
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)