Android SQLite插入前检查记录存在性时应用崩溃问题排查
看起来你遇到的是两个典型的SQL构建错误,咱们一步步来拆解解决:
首先看Logcat的两个关键报错:
- SQL语法错误
near "FROMshashaWHEREid":这明显是SQL语句里的关键字和表名/列名之间没加空格,数据库根本认不出FROM、WHERE这些关键字了。 - ID显示为
[Ljava.lang.String;@cdbe7d7:这是因为你把一个String数组直接拼进了SQL语句里,数组的默认toString()会输出它的内存地址,而不是实际的ID值。
接下来咱们逐个解决,先给你修正后的核心代码示例:
1. 正确实现「检查电影ID是否存在」的方法(以MoviesDBHelper为例)
不要手动拼接带参数的SQL,用参数化查询既避免语法错误,又防止SQL注入:
public class MoviesDBHelper extends SQLiteOpenHelper { // ... 其他已有的代码,比如构造函数、onCreate等 // 检查指定ID的电影是否已存在 public boolean isMovieExists(String movieId) { SQLiteDatabase db = this.getReadableDatabase(); boolean exists = false; // 用参数化的rawQuery,注意SQL语句里的空格! Cursor cursor = db.rawQuery( "SELECT COUNT(*) FROM " + MoviesContract.MovieEntry.TABLE_NAME + " WHERE " + MoviesContract.MovieEntry.COLUMN_MOVIE_ID + " = ?", new String[]{movieId} // 这里把ID作为参数传入,避免直接拼接 ); if (cursor.moveToFirst()) { int count = cursor.getInt(0); exists = count > 0; } cursor.close(); db.close(); return exists; } }
或者用更安全的query()方法(推荐):
public boolean isMovieExists(String movieId) { SQLiteDatabase db = this.getReadableDatabase(); String[] projection = {MoviesContract.MovieEntry.COLUMN_MOVIE_ID}; String selection = MoviesContract.MovieEntry.COLUMN_MOVIE_ID + " = ?"; String[] selectionArgs = {movieId}; Cursor cursor = db.query( MoviesContract.MovieEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, null ); boolean exists = cursor.getCount() > 0; cursor.close(); db.close(); return exists; }
2. 修正点击事件里的逻辑
确保你传入的是单个ID字符串,而不是数组:
// 假设这是你的收藏按钮点击事件 favoriteBtn.setOnClickListener(v -> { // 先获取正确的电影ID(比如从Intent或ViewModel里拿,确保是String类型) String targetMovieId = "12345"; // 替换成你实际获取ID的代码 MoviesDBHelper dbHelper = new MoviesDBHelper(getApplicationContext()); if (!dbHelper.isMovieExists(targetMovieId)) { // 不存在则插入 ContentValues values = new ContentValues(); values.put(MoviesContract.MovieEntry.COLUMN_MOVIE_ID, targetMovieId); // 补充其他电影字段,比如标题、海报地址等 // values.put(MoviesContract.MovieEntry.COLUMN_TITLE, movieTitle); // 用ContentResolver插入(如果你用了ContentProvider) getContentResolver().insert(MoviesContract.MovieEntry.CONTENT_URI, values); Toast.makeText(this, "收藏成功", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "该电影已在收藏列表中", Toast.LENGTH_SHORT).show(); } });
3. 额外检查点
- 确认
MoviesContract里的表名和列名拼写正确:比如你报错里的表名是shasha,要确保MoviesContract.MovieEntry.TABLE_NAME确实等于"shasha",列名id对应COLUMN_MOVIE_ID = "id"。 - 如果是用
ContentProvider的query方法,要确保在MoviesProvider里正确处理查询参数,不要在Provider里又犯了拼接SQL的错误。
错误原因复盘
- 语法错误根源:你之前写的SQL可能是类似
"SELECT * FROM" + TABLE_NAME + "WHEREid=" + id,FROM和表名之间、WHERE和id之间都没有空格,导致数据库把FROMshashaWHEREid当成了一个无效的标识符,直接抛出语法错误。 - ID显示为数组地址:你可能把
String[]类型的ID数组直接拼进了SQL,比如"WHEREid=" + idArray,数组的toString()默认输出[Ljava.lang.String;@xxx这种格式,这显然不是有效的ID值。
按上面的代码修正后,应该就能解决崩溃问题,正常实现「存在则不插入,不存在则插入」的逻辑了。
内容的提问来源于stack exchange,提问作者mh9
相关产品推荐
相关产品推荐

