Sqlite在现有标题上抛出“无效列标题”

时间:2016-10-04 09:27:50

标签: android database sqlite

所以我正在尝试一些我认为应该非常简单和直接的东西。我正在尝试从我创建自己的android上的Sqlite数据库加载一些数据。唯一的问题是我收到了这个错误:

W/MainActivity: onCreate started
W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
W/NotificationDbHelper: Column in cursor named: _id
W/NotificationDbHelper: Column in cursor named: title
W/NotificationDbHelper: Column in cursor named: additional
W/NotificationDbHelper: Column in cursor named: icon
W/MainActivity: onCreate ended
D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true

              [ 10-04 09:04:07.090  4272: 4272 D/         ]
              HostConnection::get() New Host Connection established 0xad17b6a0, tid 4272
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
              Process: dk.simwir.lockscreennotifications, PID: 4272
              java.lang.RuntimeException: An error occurred while executing doInBackground()
                  at android.os.AsyncTask$3.done(AsyncTask.java:309)
                  at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                  at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                  at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                  at java.lang.Thread.run(Thread.java:818)
               Caused by: java.lang.IllegalArgumentException: Invalid column title
                  at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:165)
                  at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
                  at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)
                  at android.content.ContentResolver.query(ContentResolver.java:491)
                  at android.content.CursorLoader.loadInBackground(CursorLoader.java:64)
                  at android.content.CursorLoader.loadInBackground(CursorLoader.java:56)
                  at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:312)
                  at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:69)
                  at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:66)
                  at android.os.AsyncTask$2.call(AsyncTask.java:295)
                  at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                  at java.lang.Thread.run(Thread.java:818) 

尝试从表中加载数据时。主要错误接缝为:Caused by: java.lang.IllegalArgumentException: Invalid column title。它声称该列无效,但正如您在日志输出中看到的那样,我创建它似乎在那里:W/NotificationDbHelper: Column in cursor named: title。我从android adb访问了数据库,并确认它存在:

Table schema

在研究问题时,我发现的主要'修复'是我需要将其添加到投影地图中,但我尝试过,但它仍然无法修复它。

错误似乎不是直接在我的代码中发生,而是在后台线程上,因此日志输出使得难以查明错误。但是,数据库中的信息将加载到以下代码中:

Cursor cursor = notificationDbHelper.getAllActiveNotifications();
    if(cursor == null){
        Log.e(TAG, "Cursor returned null");
        Toast toast = Toast.makeText(getApplicationContext(), R.string.cursor_null_error, Toast.LENGTH_LONG);
        toast.show();
    }else if (cursor.getCount()==0){
        Log.e(TAG, "Cursor returned empty");
        Toast toast = Toast.makeText(getApplicationContext(), R.string.no_active_notifications, Toast.LENGTH_SHORT);
        toast.show();
    }else{
        String[] fromColumns = {ActiveNotificationEntry.COLUM_NAME_TITLE, ActiveNotificationEntry.COLUM_NAME_ADDITIONAL_TEXT};
        int[] toViews = {R.id.notification_title, R.id.notification_additional_text};

        cursorAdapter = new SimpleCursorAdapter(this, R.id.simple_notification, cursor, fromColumns, toViews, 0);
        notificationList.setAdapter(cursorAdapter);
    }

与数据库交互的getAllActiveNotifications函数如下所示:

public Cursor getAllActiveNotifications(){
    HashMap<String, String> myProjectionMap = new HashMap<String, String>();

    myProjectionMap.put(ActiveNotificationEntry._ID, ActiveNotificationEntry._ID);
    myProjectionMap.put(ActiveNotificationEntry.COLUM_NAME_TITLE, ActiveNotificationEntry.COLUM_NAME_TITLE);
    myProjectionMap.put(ActiveNotificationEntry.COLUM_NAME_ADDITIONAL_TEXT, ActiveNotificationEntry.COLUM_NAME_ADDITIONAL_TEXT);
    myProjectionMap.put(ActiveNotificationEntry.COLUM_NAME_ICON, ActiveNotificationEntry.COLUM_NAME_ICON);

    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    queryBuilder.setTables(ActiveNotificationEntry.TABLE_NAME);
    queryBuilder.setProjectionMap(myProjectionMap);

    SQLiteDatabase db = this.getReadableDatabase();

    Cursor cursor = queryBuilder.query(db,CURSOR_COLUMNS, null, null, null, null, null);

    if (cursor!=null){
        for(int i = 0; i < cursor.getColumnCount(); i++){
            Log.w("NotificationDbHelper", "Column in cursor named: " + cursor.getColumnName(i));
        }
        cursor.moveToFirst();
        return cursor;
    }else {
        Log.e("NotificationDbHelper", "Cursor returned null");
        return null;
    }
}

游标colums数组包含:

public static final String[] CURSOR_COLUMNS = new String[]{
        ActiveNotificationEntry._ID,
        ActiveNotificationEntry.COLUM_NAME_TITLE,
        ActiveNotificationEntry.COLUM_NAME_ADDITIONAL_TEXT,
        ActiveNotificationEntry.COLUM_NAME_ICON};

该表与getActiveNotification()在同一文件中创建。该文件扩展了SQLiteOpenHelper,并在创建时使用:

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
    sqLiteDatabase.execSQL(NotificationContract.SQL_CREATE_ENTRIES);
}

此处引用的SQL_CREATE_ENTRIES常量为:

public static final String SQL_CREATE_ENTRIES =
        "CREATE TABLE " + ActiveNotificationEntry.TABLE_NAME + " (" +
                ActiveNotificationEntry._ID + " INTEGER PRIMARY KEY" + COMMA_SEP +
                ActiveNotificationEntry.COLUM_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
                ActiveNotificationEntry.COLUM_NAME_ICON + TEXT_TYPE + COMMA_SEP +
                ActiveNotificationEntry.COLUM_NAME_ADDITIONAL_TEXT + TEXT_TYPE + " )";

我尝试过一个简单的database.query而不是QueryBuilder,但结果相同:

Cursor cursor = db.query(ActiveNotificationEntry.TABLE_NAME, CURSOR_COLUMNS,null,null,null,null,null,null);

即使错误消息显示它在“doInBackground()”中,此时也不应该有任何asynkTasks处于活动状态。

我收集了我认为与gist相关的所有文件。 MainActivity上面使用的信息在第87行。

1 个答案:

答案 0 :(得分:0)

如果必须检索单个表,则使用SQLiteQueryBuilder不是一个好的解决方案。它主要用于连接查询。

如果您需要进行加入,请查看this link for example

如果您需要查询简单表格,请使用query function

SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(myTable, myColumns, null, null, null, null, null);

你已经完成了