当前位置:  开发笔记 > 数据库 > 正文

Android:使用ContentResolver时的SQLite事务

如何解决《Android:使用ContentResolver时的SQLite事务》经验,为你挑选了2个好方法。

目标:从XML数据刷新数据库

过程:

开始交易

从表中删除所有现有行

每个解析XML的主要元素插入主表并获取PK

每个主元素的子元素记录插入到第二个表中,从上一步提供FK

提交交易

数据库操作相当标准的东西.问题是CRUD操作不是在内部完成,ContentProvider而是使用ContentResolver插件,例如看起来像resolver.insert(CONTENT_URI, contentValues).ContentResolver API似乎没有任何与事务相关的东西,我无法使用,bulkInsert因为我间歇性地插入2个表(另外我也希望delete在事务内部).

我正在考虑ContentProvider通过使用注册我自定义的监听器,registerContentObserver但由于ContentResolver#acquireProvider隐藏了方法,我如何获得正确的引用?

我运气不好吗?



1> Catalin Moro..:

我已经看到了在谷歌I/O应用程序的源代码,它们覆盖ContentProviderapplyBatch()它的内部方法和使用交易.所以,你创建一批ContentProviderOperations然后调用getContentResolver().applyBatch(uri_authority, batch).

我打算用这种方法看看它是如何工作的.我很好奇是否有其他人尝试过它.


我尝试过这种方法,效果很好.但是,批处理中的每个ContentProviderOperation都是原子操作.我的意思是没有办法正确处理主 - 细节关系的相关操作,其中第一个操作创建的身份密钥需要作为后续操作的输入.之前我曾问过这个问题,但得到了零响应(http://stackoverflow.com/questions/3224857/master-detail-using-contentresolver-applybatch).

2> David Burstr..:

从kaciula提到的使用ContentProviderOperation的Android 2.1以来,可以相当干净地进行基于事务的多表插入.

构建ContentProviderOperation对象时,可以调用.withValueBackReference(fieldName,refNr).使用applyBatch应用操作时,结果是insert()调用提供的ContentValues对象将注入一个整数.整数将使用fieldName String键入,并且其值将从之前应用的ContentProviderOperation的ContentProviderResult中检索,由refNr索引.

请参阅下面的代码示例.在示例中,在table1中插入一行,然后在表2中插入行时将结果ID(在本例中为"1")用作值.为简便起见,ContentProvider未连接到数据库.在ContentProvider中,有一些打印输出适合添加事务处理.

public class BatchTestActivity extends Activity {
    /** Called when the activity is first created. */
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ArrayList list = new
            ArrayList();

        list.add(ContentProviderOperation.
            newInsert(BatchContentProvider.FIRST_URI).build());
        ContentValues cv = new ContentValues();
        cv.put("name", "second_name");
        cv.put("refId", 23);

        // In this example, "refId" in the contentValues will be overwritten by
        // the result from the first insert operation, indexed by 0
        list.add(ContentProviderOperation.
            newInsert(BatchContentProvider.SECOND_URI).
            withValues(cv).withValueBackReference("refId", 0).build());

        try {
            getContentResolver().applyBatch(
                BatchContentProvider.AUTHORITY, list);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            e.printStackTrace();
        }
    }
}

public class BatchContentProvider extends ContentProvider {

    private static final String SCHEME = "content://";
    public static final String AUTHORITY = "com.test.batch";

    public static final Uri FIRST_URI =
        Uri.parse(SCHEME + AUTHORITY + "/" + "table1");
    public static final Uri SECOND_URI =
        Uri.parse(SCHEME + AUTHORITY + "/" + "table2");


    public ContentProviderResult[] applyBatch(
        ArrayList operations)
            throws OperationApplicationException {
        System.out.println("starting transaction");
        ContentProviderResult[] result;
        try {
            result = super.applyBatch(operations);
        } catch (OperationApplicationException e) {
            System.out.println("aborting transaction");
            throw e;
        }
        System.out.println("ending transaction");
        return result;
    }

    public Uri insert(Uri uri, ContentValues values) {
        // this printout will have a proper value when
        // the second operation is applied
        System.out.println("" + values);

        return ContentUris.withAppendedId(uri, 1);
    }

    // other overrides omitted for brevity
}

推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有