2011-04-27 92 views
23

我試圖調試一個真正的設備上我的應用程序,但我得到這個錯誤:java.lang.IllegalArgumentException異常:列「_id」不存在

ERROR/AndroidRuntime(981): Caused by: java.lang.IllegalArgumentException: column '_id' does not exist

當我在模擬器上測試,錯誤不會出現。該錯誤是在下面的代碼的最後一行給出:

adapter = new SimpleCursorAdapter(this, R.layout.list_item, c, new String[] { 
      DataHandlerDB.CONTACT_NAME_COL, 
      DataHandlerDB.CONTACT_NUMBER_COL, 
      DataHandlerDB.CONTACT_DURATION_COL, 
      DataHandlerDB.CONTACT_DATE_COL }, new int[] { 
      R.id.contact_name, R.id.phone_number, R.id.duration, R.id.date }); 

這裏是我的活動:

public class MyActivity extends Activity { 

    private static final String LOG_TAG = "MyActivity"; 
    private ListView listview; 
    private SimpleCursorAdapter adapter;   
    private DataHandlerDB handler; 
    private SQLiteDatabase db; 
    private OpenHelper helper; 
    private Cursor c; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState);  
     setContentView(R.layout.main); 

     helper = new OpenHelper(this); 
     db = helper.getWritableDatabase(); 
     helper.onCreate(db); 
     setBasicContent(); 
     c.close(); 
    } 


    @Override 
    public void onDestroy(){ 

     super.onDestroy(); 
     DataHandlerDB.makeTheSelection(this).close(); 
     db.close(); 
     helper.close(); 

    } 

    @Override 
    public void onPause(){ 

     super.onPause(); 
     DataHandlerDB.makeTheSelection(this).close(); 
     db.close(); 
     helper.close(); 

    } 

    @Override 
    public void onStop(){ 

     super.onStop(); 
     DataHandlerDB.makeTheSelection(this).close(); 
     db.close(); 
     helper.close(); 

    } 


    @Override 
    protected void onResume(){ 

     super.onResume(); 
     setBasicContent(); 

    } 

    public void setBasicContent() { 

     listview = (ListView) findViewById(R.id.list_view); 

     Log.i(LOG_TAG, "listview " + listview); 

     c = DataHandlerDB.makeTheSelection(this); 

     c.moveToFirst(); 

     if(db.isOpen()) 
      Log.i(LOG_TAG, "db is opened"); 

     Log.i(LOG_TAG, "cursor: " + c.getCount()); 

     startManagingCursor(c); 

     adapter = new SimpleCursorAdapter(this, R.layout.list_item, c, new String[] { 
       DataHandlerDB.CONTACT_NAME_COL, 
       DataHandlerDB.CONTACT_NUMBER_COL, 
       DataHandlerDB.CONTACT_DURATION_COL, 
       DataHandlerDB.CONTACT_DATE_COL }, new int[] { 
       R.id.contact_name, R.id.phone_number, R.id.duration, R.id.date }); 

     Log.i(LOG_TAG, "before setAdapter"); 
     Toast.makeText(this, "Before setAdapter", Toast.LENGTH_SHORT).show(); 

     listview.setAdapter(adapter); 

     db.close(); 

     if(db.isOpen()){ 

      Log.i(LOG_TAG, "db is opened."); 

     } 

     if(!c.isClosed()){ 

      Log.i(LOG_TAG, "cursor is opened"); 

     }   
    }  
} 

功能的查詢,並返回Cursor在類DataHandlerDB

public class DataHandlerDB { 

private static final String DATABASE_NAME = "calls.db"; 
private static final int DATABASE_VERSION = 1; 

protected static String CONTACT_NAME_COL = "contact_name"; 
protected static String CONTACT_NUMBER_COL = "contact_number"; 
protected static String CONTACT_DURATION_COL = "duration"; 
protected static String CONTACT_DATE_COL = "date"; 
protected static String CONTACT_MONTH_COL = "month"; 

// create the DB 
public static SQLiteDatabase createDB(Context ctx) { 
    OpenHelper helper = new OpenHelper(ctx); 
    SQLiteDatabase db = helper.getWritableDatabase(); 
    helper.onCreate(db); 
    helper.onOpen(db); 
    db.close(); 
    return db; 
} 

public static Cursor makeTheSelection(Context ctx) { 

    OpenHelper helper = new OpenHelper(ctx); 
    SQLiteDatabase db = helper.getWritableDatabase(); 

    Cursor cursor = db.query(TABLE_NAME_2, null, null, null, null, null, 
      "duration desc"); 

    cursor.moveToFirst(); 
    db.close(); 

    return cursor; 
} 
    // class OpenHelper 
public static class OpenHelper extends SQLiteOpenHelper { 

    private final Context mContext; 

    OpenHelper(Context context) { 

     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     this.mContext = context; 

    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
     Log.i(LOG_TAG, "entrou no onCreate"); 
     String[] sql = mContext.getString(
       R.string.MyAppDatabase_OnCreate).split("\n"); 

     db.beginTransaction(); 

     try { 
      execMultipleSQL(db, sql); 
      db.setTransactionSuccessful(); 
     } catch (SQLException e) { 

      Log.e("Error creating tables and debug data", e.toString()); 
      throw e; 

     } finally { 
      db.endTransaction(); 

     } 
    } 

    private void execMultipleSQL(SQLiteDatabase db, String[] sql) { 

     for (String s : sql) { 

      if (s.trim().length() > 0) { 

       db.execSQL(s); 
      } 
     } 

    } 

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

     Log.w("MyDB Database", 
     "Upgrading database, this will drop tables and recreate."); 
     db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); 

    } 

    @Override 
    public void onOpen(SQLiteDatabase db) { 

     super.onOpen(db); 
    } 
} 
} 

這是帶有SQL命令的XML文件:

<string name="MyAppDatabase_OnCreate"> 
    "CREATE TABLE IF NOT EXISTS contact_data(_id INTEGER PRIMARY KEY AUTOINCREMENT, contact_id INTEGER, contact_name VARCHAR(50), number_type VARCHAR(50), contact_number VARCHAR(50), duration TIME, duration_sum TIME, date DATE, current_time TIME, cont INTEGER, type VARCHAR, month VARCHAR(50), day VARCHAR(50), year VARCHAR(50));" 
</string> 

我認爲應用程序在首次啓動時並未創建數據庫。我這麼認爲是因爲它可以找到_id列,但它明確地寫在XML代碼中,用_id列創建它。我也認爲,因爲我明確寫了SELECT方法中的列,包括_id。我這樣做是這樣的:

Cursor cursor = db.query(TABLE_NAME_2, 
       new String[]{ 
       "_id", 
       "contact_id", 
       "contact_name", 
       "number_type", 
       "contact_number", 
       "duration", 
       "duration_sum", 
       "date", 
       "current_time", 
       "cont", "type", 
       "month", 
       "day", 
       "year"}, null, null, null, null, 
       "duration desc"); 

在這種情況下,我收到的錯誤幾乎是一樣的:

Caused by: android.database.sqlite.SQLiteException: no such column: _id: , while compiling: SELECT _id, contact_id, contact_name, number_type, contact_number, duration, duration_sum, date, current_time, cont, type, month, day, year FROM contact_data ORDER BY duration desc

我登錄數據庫的第一列像這樣:

Log.i(LOG_TAG, "Cursor(0)" + cursor.getColumnName(0)); 

它印上id,而不是_id。正如你所看到的,在陳述中寫有_id。有關如何解決此問題的任何建議?

+0

從設備上完全卸載應用程序(例如,設置>應用程序>管理應用程序),然後重試。我懷疑你的數據庫已經存在,沒有'_id'列。 – CommonsWare 2011-04-27 23:56:46

+0

我照你說的做了,但錯誤依然存在。 =( – rogcg 2011-04-28 00:03:56

回答

37

您正在嘗試使用需要的光標稱爲_id。就像編輯表創建語句並添加一個名爲_id的列一樣簡單。

其declartion看起來是這樣的:

_id INTEGER PRIMARY KEY AUTOINCREMENT 

添加這一點,那麼你將能夠使用它。我相信這是爲了使用SimpleCursorAdapter而需要的。

UPDATE

"CREATE TABLE IF NOT EXISTS contact_data(_id INTEGER PRIMARY KEY AUTOINCREMENT, contact_id INTEGER, contact_name VARCHAR(50), number_type VARCHAR(50), contact_number VARCHAR(50), duration TIME, duration_sum TIME, date DATE, current_time TIME, cont INTEGER, type VARCHAR, month VARCHAR(50), day VARCHAR(50), year VARCHAR(50));" 

解決方案:添加一個空格左括號之間 '(' 和_id

+4

'CursorAdapter'總是需要一個名爲'_id'的列 – surfer190 2015-06-15 14:04:37

+1

你可以使用別名而不是創建它!如果你已經擁有_id列但有其他名字,只需在你的sql查詢中使用AS來更改你的主鍵名: {SELECT myprimarykey AS _id,name FROM TABLE WHERE name LIKE'%queryfilter%';} – jcasadellaoller 2016-04-21 15:17:03

9

我有類似的問題,因爲我沒有加入_id列到投影參數,因此將_id添加到投影查詢的tions參數是解決方案。(評論說@nobugs


例子:

String[] projections = {"_id", "name", "age"}; 

Cursor cursor = db.query(domainClass.getSimpleName(), projections, 
    null, null, null, null, null); 
+1

這是我的解決方案 傻了,謝謝。 – 2017-07-03 04:10:12

2

首先卸載該應用程序,然後執行以下步驟:

  1. 清潔項目
  2. 重建他的項目
  3. 調試應用程序(Shift + F9)
相關問題