【问题标题】:Sqlite throws "invalid column title" on existing titleSqlite 在现有标题上抛出“无效的列标题”
【发布时间】:2016-10-04 21:17:33
【问题描述】:

所以我正在尝试一些我认为应该非常简单和直接的东西。我正在尝试从我自己创建的 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 访问了数据库并确认它存在:

在研究问题时,我发现的主要“修复”是我需要将其添加到投影地图中,但我尝试了,但仍然没有修复。

错误似乎不是直接发生在我的代码中,而是发生在后台线程中,因此日志输出很难查明错误。但是来自数据库的信息是在这段代码中加载的:

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;
    }
}

光标列数组包含以下内容:

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 行。

【问题讨论】:

  • 可能是的,但是在此之前您是否运行过创建表查询?你能发布这个查询吗?

标签: android database sqlite


【解决方案1】:

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

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

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

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

你已经完成了

【讨论】:

  • 我一开始就是这样做的,QueryBuilder 是故障排除过程的一部分。之前的行是Cursor cursor = db.query(ActiveNotificationEntry.TABLE_NAME, CURSOR_COLUMNS,null,null,null,null,null,null); 但回到这里会产生同样的错误。
  • @simwir 此代码必须有效,我几乎在每个项目中都使用它。你用你所说的方式做错了什么。在您的问题中添加执行它的异步任务,在错误中“doInBackground()”中存在问题
  • 问题是,它没有在异步测试中被调用。我已经在gist 中发布了我认为相关的文件。上面问题中的代码 sn-p 来自 MainActivity.java 中的第 87 行。
  • @simwir 嗯,很有趣。究竟是哪一行引发了错误?
  • 就是这样,我的代码中没有一行抛出错误,我不认为。我已经用调试器逐步完成了代码,它可以完成它。然后,当模拟器恢复正常操作时,程序崩溃。我正在打印一个 onCreate 开始和结束,并且两者都在应用程序崩溃之前打印。
猜你喜欢
  • 2016-02-27
  • 2019-03-03
  • 2017-08-07
  • 1970-01-01
  • 1970-01-01
  • 2021-03-26
  • 2013-02-17
  • 2013-07-29
相关资源
最近更新 更多