我有一个databaseHelper类,其中具有以下功能:

public SQLiteDatabase returnDB(){

        return DBHelper.getWritableDatabase();
    }


在我的主类中(异步任务-onPreExecute):

            dbHelper = new DBAdapter(getApplicationContext());
            dbHelper.open();

            mDb = dbHelper.returnDB();
            mDb.beginTransaction();


在doInBackground中,我将查询处理为:

dbHelper.insert(dateToInsert, CONTACT_NAME, String.valueOf(days), String.valueOf(hou), CONTACT_IMAGE_URI, String.valueOf(min),String.valueOf(mon), String.valueOf(secon), CONTACT_ID, String.valueOf(weeks), String.valueOf(years));


然后在onPostExecute中:

mDb.endTransaction();
dbHelper.close();


但是,当我尝试在异步任务执行后立即将值提取到列表视图中时,出现数据库锁定错误。下面是LogCat:

02-08 14:40:06.587: E/SQLiteLog(6394): (5) database is locked
02-08 14:40:06.588: D/SQLiteConnection(6394): executeForString took 2505ms - failed, sql="PRAGMA journal_mode", exception="database is locked (code 5): , while compiling: PRAGMA journal_mode"
02-08 14:40:06.602: E/SQLiteDatabase(6394): Failed to open database '/data/data/com.exa.birthdayrem/databases/Bdr'.
02-08 14:40:06.602: E/SQLiteDatabase(6394): android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:882)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:627)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:313)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:287)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:860)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at com.exa.birthdayrem.DBAdapter.returnDB(DBAdapter.java:156)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at com.exa.birthdayrem.LoaderClass$MagicCall.onPostExecute(LoaderClass.java:457)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at com.exa.birthdayrem.LoaderClass$MagicCall.onPostExecute(LoaderClass.java:1)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.os.AsyncTask.finish(AsyncTask.java:631)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.os.AsyncTask.access$600(AsyncTask.java:177)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.os.Looper.loop(Looper.java:153)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.app.ActivityThread.main(ActivityThread.java:5000)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at java.lang.reflect.Method.invokeNative(Native Method)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at java.lang.reflect.Method.invoke(Method.java:511)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at dalvik.system.NativeStart.main(Native Method)


我这样做对吗?我没有看到很多性能提升吗?

最佳答案

这是如何在DatabaseHelper中处理事务的示例。您需要确保仅创建一次助手,例如通过使其成为单例。为了同时具有多个读取器更好的性能,可以用ReadWriteLock替换ReentrantLock。

DbHelper helper = new DbHelper();

private void DoSimpleInsert()
{
    helper.InsertA(items);
}

private void DoComplexInsert()
{
    helper.BeginTransaction();
    helper.InsertA(items);
    helper.InsertB(items);
    helper.EndTransaction();
}

public class DbHelper
{
    private SQLiteDatabase db;
    private boolean isExpliciteTransaction;
    private ReentrantLock lock = new ReentrantLock();

    public void BeginTransaction()
    {
        isExpliciteTransaction = true;
        db.beginTransaction();
    }

    public void EndTransaction()
    {
        isExpliciteTransaction = false;
        db.endTransaction();
    }

    public void InsertA(ClassA[] items)
    {
        lock.lock();
        try
        {
            if (!isExpliciteTransaction)
            {
                db.beginTransaction();
            }

            // Do the inserts here

            if (!isExpliciteTransaction)
            {
                db.endTransaction();
            }
        }
        finally
        {
            lock.unlock();
        }
    }

    public void InsertB(ClassB[] items)
    {
        lock.lock();
        try
        {
            if (!isExpliciteTransaction)
            {
                db.beginTransaction();
            }

            // Do the inserts here

            if (!isExpliciteTransaction)
            {
                db.endTransaction();
            }
        }
        finally
        {
            lock.unlock();
        }
    }
}

09-27 15:19