Android SQLite同一个游标用于多个表:

时间:2013-04-26 03:21:49

标签: android-sqlite

在我的Android应用中,我有以下SQLite接口类

package com.songs.lookup;

import java.util.ArrayList;
import java.util.List;

import com.songs.MainActivity2;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;

public class CacheDB {

    public CacheDB(Context context){
        this.dbHelper = new CacheDBHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    private Cursor songCursor;
    private Cursor tuneCursor;
    private Cursor personCursor;
    private Context context;
    private CacheDBHelper dbHelper;
    private SQLiteDatabase db;
    private static final String DATABASE_NAME = "SONGS";
       private static final int DATABASE_VERSION = 1;
       private static final String SONG_TABLE_NAME = "songs";
       private static final String TUNE_TABLE_NAME = "tunes";
       private static final String PERSON_TABLE_NAME = "persons";
       private static final String COLUMN_NAME = "name";
        String selectsongQuery = "SELECT  * FROM " + SONG_TABLE_NAME;
        String selecttuneQuery = "SELECT  * FROM " + TUNE_TABLE_NAME;
        String selectpersonQuery = "SELECT  * FROM " + PERSON_TABLE_NAME;



       private static final String SONG_TABLE_CREATE =
                "CREATE TABLE " + SONG_TABLE_NAME + " (" +
                COLUMN_NAME + " TEXT);";

       private static final String TUNE_TABLE_CREATE =
                        "CREATE TABLE " + TUNE_TABLE_NAME + " (" +
                        COLUMN_NAME + " TEXT);";

       private static final String PERSON_TABLE_CREATE =
                        "CREATE TABLE " + PERSON_TABLE_NAME + " (" +
                        COLUMN_NAME + " TEXT);";

   class CacheDBHelper extends SQLiteOpenHelper{ 
     SQLiteDatabase readDb = null;
     SQLiteDatabase writeDb = null;
   public CacheDBHelper(Context context, String name, CursorFactory factory,
            int version) {
       super(context, DATABASE_NAME, null, DATABASE_VERSION);
       System.out.println("After the cachedbhelper");

    }

        @Override
        public void onCreate(SQLiteDatabase db) {
            System.out.println("Here inside the oncreate of cacheDBHelper");
            db.execSQL(SONG_TABLE_CREATE);
            db.execSQL(TUNE_TABLE_CREATE);
            db.execSQL(PERSON_TABLE_CREATE);

        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }

        public SQLiteDatabase getReadDb()
           {
            if(readDb == null)
              readDb = this.getReadableDatabase();
            else; 
            return  readDb;
           }
        public SQLiteDatabase getWriteDb()
           {
            if(writeDb == null)
              writeDb = this.getReadableDatabase();
            else;
            return  writeDb;
           }
   }

   @SuppressLint("NewApi")
public void performOperation(String Operation, String table, ArrayList<String> array1)
   {
       SQLiteDatabase db = dbHelper.getWriteDb();

       String INSERT = "insert into "   
                + table + " (" + COLUMN_NAME + ") values (?)";

       String DELETE = "delete from " + table; 

       String FETCH = "select DISTINCT(" + COLUMN_NAME + "from " + table + ")";

       db.beginTransaction();

       SQLiteStatement dbStmt = db.compileStatement(Operation.equals("INSERT") ? INSERT : DELETE);

       if(Operation.equals("INSERT"))
       {  
            int aSize = array1.size();



                for (int i = 0; i < aSize; i++) {
                    dbStmt.bindString(1, array1.get(i));
                    dbStmt.executeInsert();
            }
       }

       if(Operation.equals("DELETE"))
       {
           dbStmt.executeUpdateDelete();
       }


       db.setTransactionSuccessful();
       db.endTransaction();


       try {
            db.close();
            dbHelper.close();
           } catch (Exception e) {
            e.printStackTrace();
           }
        }

   public List<String> fetchData(String table)
   {
       List<String> result = new ArrayList<String>();
       SQLiteDatabase db = this.dbHelper.getReadDb(); 
       result = this.fetchDatafromDB(table, db);

       dbHelper.close();
       return result;
   }


   public List<String> fetchDatafromDB(String table, SQLiteDatabase db) {
        List<String> list = new ArrayList<String>(); 
        String selectQuery = "SELECT  * FROM " + table;    
     System.out.println("The cursor plac eeee");

       if(table == "song")
       {
         songCursor = db.rawQuery(selectQuery, null);
         list = parseCursor(songCursor);
         songCursor.close();
       }
       else if(table == "tune")
       {
           tuneCursor = db.rawQuery(selectQuery, null);
         list = parseCursor(tuneCursor);
         tuneCursor.close();
       }
       else
       {
           personCursor = db.rawQuery(selectQuery, null);
         list = parseCursor(personCursor);
         personCursor.close();
       }
         db.close();
         return list;
}

  public List<String> parseCursor(Cursor cursor)
  {
      List<String> list = new ArrayList<String>();
        if (cursor.moveToFirst()) {
            do {
                list.add(cursor.getString(0));
            } while (cursor.moveToNext());
        }
            cursor.close();
        return list; 
  }

}

在另一个我从DB查找数据的类中 我连续为所有三个表调用fetchData方法。第一个表操作正常。但是对于第二个表,我收到以下错误:

04-24 06:27:50.706: E/AndroidRuntime(2354): FATAL EXCEPTION: main
04-24 06:27:50.706: E/AndroidRuntime(2354): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.songs/com.songs.MainActivity2}: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.songs/databases/songS
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.app.ActivityThread.access$600(ActivityThread.java:130)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.os.Handler.dispatchMessage(Handler.java:99)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.os.Looper.loop(Looper.java:137)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.app.ActivityThread.main(ActivityThread.java:4745)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at java.lang.reflect.Method.invokeNative(Native Method)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at java.lang.reflect.Method.invoke(Method.java:511)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at dalvik.system.NativeStart.main(Native Method)
04-24 06:27:50.706: E/AndroidRuntime(2354): Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.songs/databases/songS
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1310)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1253)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at com.songs.lookup.CacheDB.fetchDatafromDB(CacheDB.java:181)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at com.songs.lookup.CacheDB.fetchData(CacheDB.java:155)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at com.songs.lookup.LookUpData.getData(LookUpData.java:38)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at com.songs.MainActivity2.onCreate(MainActivity2.java:66)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.app.Activity.performCreate(Activity.java:5008)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
04-24 06:27:50.706: E/AndroidRuntime(2354):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
04-24 06:27:50.706: E/AndroidRuntime(2354):     ... 11 more

以前有过类似的问题,但我没有看到任何从多个表创建或获取的问题。

基本上是失败的行

       personCursor = db.rawQuery(selectQuery, null);

在我使用单个游标并将其初始化为null之前,我认为我需要单独的游标,这可能是问题,但似乎并非如此。

2 个答案:

答案 0 :(得分:1)

您在多个地方(db.close()dbHelper.close()performOperation)呼叫fetchDataFromDBfetchData。一旦你打电话关闭,你就不能再创建一个全新的DbHelper来查询数据库了。这就是你得到异常的原因,它告诉你数据库已关闭。移除你的近距离通话你应该没问题:你应该在你的活动close中调用明确的onDestroy方法。

答案 1 :(得分:0)

请检查您是否输入了错误的表格名称...该表格的名称为“tunes”。在fetchdatafromDB()中,您正在检查名称“tune”。将其更改为“曲调”并更改其他名称。

  if(table == "songs")
   {
     songCursor = db.rawQuery(selectQuery, null);
     list = parseCursor(songCursor);
     songCursor.close();
   }

希望它有所帮助。