【问题标题】:SQLite INNER JOIN throws a NullPointerExceptionSQLite INNER JOIN 抛出 NullPointerException
【发布时间】:2012-03-05 17:20:37
【问题描述】:

我不明白为什么查询最终会抛出 NullPointerException

我的数据库包含两个表。第一个名为TABLE_WORDS 包含单词;第二个名为TABLE_TRANS 包含翻译。一个词可以有多种翻译。

public static final String CREATE_TABLE_WORDS = "CREATE TABLE " + TABLE_WORDS + 
    " (" + WORDS_ID + " INTEGER PRIMARY KEY, " + WORDS_WORD + 
    " TEXT);";

public static final String CREATE_TABLE_TRANS = "CREATE TABLE " + TABLE_TRANS + 
    " (" + TRANS_ID + " INTEGER PRIMARY KEY, " + 
    TRANS_WORD + " TEXT, " + 
    TRANS_FOREIGN_ID_WORD + " INTEGER, " +
    "FOREIGN KEY (" + TRANS_FOREIGN_ID_WORD + ") REFERENCES " + TABLE_WORDS + "(" + WORDS_ID + "));";

我通过单词 ID 查询翻译,并抛出 NPE

public Cursor queryTransesByWord(int idSend) {

    String query = "SELECT " + DbHelper.TABLE_WORDS + "." + DbHelper.WORDS_WORD + ", " +
        DbHelper.TABLE_TRANS + "." + DbHelper.TRANS_WORD + 
        " FROM " + DbHelper.TABLE_WORDS + 
        " INNER JOIN " + DbHelper.TABLE_TRANS + 
        " ON " + DbHelper.TABLE_WORDS + "." + DbHelper.WORDS_ID + "=" + 
        DbHelper.TABLE_TRANS + "." + DbHelper.TRANS_FOREIGN_ID_WORD + " WHERE " +
        DbHelper.TABLE_WORDS + "." + DbHelper.WORDS_ID + "="+ idSend; 

    Cursor cur = db.rawQuery(query, null); // NullPointer always throws here

    if (cur != null)
        cur.moveToFirst();
    else
        Log.e(Constants.LOG_TAG, Constants.DB_ADAPTER_CLASS_NAME_SEP + "queryTransesByWord cursor is null");
    return cur;
}

【问题讨论】:

    标签: android sqlite nullpointerexception


    【解决方案1】:

    好吧,给定你的代码:

    Cursor cur = db.rawQuery(query, null); // NullPointer always throws here
    

    这表明db 为空。该语句中没有其他取消引用操作 - 因此,除非堆栈跟踪 实际上 在其中某处显示 rawQuery,否则 db 为空。你没有给出任何迹象表明 db 应该被分配一个非空值,但这是首先要检查的事情......

    顺便说一句,不要在你的 SQL 中包含这样的值 - 这是SQL injection attacks 的秘诀。请改用参数化 SQL。

    【讨论】:

    • db 不为空,我在查询之前打开它。公共类 DbAdapter { 私有 DbHelper 助手;私有 SQLiteDatabase 数据库;私有 int openStatus; public void openForReading() { if (openStatus == 0) { db = helper.getReadableDatabase();开放状态 = 1; } // if (openStatus == 0) else if (openStatus == 2) { helper.close(); db = helper.getReadableDatabase(); } // 嵌套 if (openStatus == 2) Log.i(Constants.LOG_TAG, Constants.DB_ADAPTER_CLASS_NAME_SEP + "openForReading succeed"); }
    • @RedPlanet:在这种情况下,您显示的行不会位于堆栈跟踪的顶部。 (这就是为什么你应该在你的问题中包含堆栈跟踪。)但看起来如果你没有调用openForReading 那么db 为空......
    【解决方案2】:

    在我的情况下,我应该使用

    String query = "SELECT " + DbHelper.TABLE_WORDS + "." + DbHelper.WORDS_WORD + ", " +
        DbHelper.TABLE_TRANS + "." + DbHelper.TRANS_WORD + 
        " FROM " + DbHelper.TABLE_WORDS + 
        " INNER JOIN " + DbHelper.TABLE_TRANS + 
        " ON " + DbHelper.TABLE_WORDS + "." + DbHelper.WORDS_ID + "=" + 
        DbHelper.TABLE_TRANS + "." + DbHelper.TRANS_FOREIGN_ID_WORD + " WHERE " +
        DbHelper.TABLE_WORDS + "." + DbHelper.WORDS_ID + "=?";    
    
    Cursor cur = db.rawQuery(query, new String[] { Integer.toString(idSend) } );
    

    我说的对吗?

    【讨论】:

      【解决方案3】:
      String query = "SELECT " + DbHelper.TABLE_WORDS + "." + DbHelper.WORDS_WORD + ", " +
      DbHelper.TABLE_TRANS + "." + DbHelper.TRANS_WORD + 
      " FROM " + DbHelper.TABLE_WORDS + 
      " INNER JOIN " + DbHelper.TABLE_TRANS + 
      " ON " + DbHelper.TABLE_WORDS + "." + DbHelper.WORDS_ID + "=" + 
      DbHelper.TABLE_TRANS + "." + DbHelper.TRANS_FOREIGN_ID_WORD + " WHERE " +
      DbHelper.TABLE_WORDS + "." + DbHelper.WORDS_ID + "=?";    
      
      Cursor cur = db.rawQuery(query, new String[] { Integer.toString(idSend) } );
      

      这对我有用:-)

      【讨论】:

        猜你喜欢
        • 2020-09-19
        • 1970-01-01
        • 2018-10-22
        • 2019-03-03
        • 2015-08-15
        • 2022-01-08
        • 2012-01-09
        • 2019-03-02
        • 2018-06-27
        相关资源
        最近更新 更多