当我试图从 SQLite 数据库中删除一行时,为什么我的 android 应用程序崩溃了?科特林

Why is my android app crashing when I'm trying to delete a row from SQLite database? Kotlin

所以我正在创建一个 GitHub 移动设备,我可以在其中搜索用户并查看个人资料。我正在尝试创建一个收藏夹功能,单击详细信息页面中的按钮时,可以将用户添加到收藏夹数据库。我已经创建了 DatabaseHandler class 并且还设置了要添加到 activity 中的函数。这是数据库处理程序的代码:

class DatabaseHandler(context:Context):SQLiteOpenHelper(context,DATABASE_NAME,null,DATABASE_VERSION) {

companion object {
    private const val DATABASE_VERSION = 1
    private const val DATABASE_NAME = "FavoriteUsersDatabase"
    private const val TABLE_NAME = "FavoriteTable"

    private const val KEY_ID = "_id" //primary key -> unique for each record
    private const val KEY_USERNAME = "username"
}

//onCreate is called once the database is created
override fun onCreate(db: SQLiteDatabase?) {
    //creating table with fields -> using SQL command
    val CREATE_USER_TABLE = ("CREATE TABLE "+ TABLE_NAME+
            "("+ KEY_ID+" INTEGER PRIMARY KEY,"+
            KEY_USERNAME+" TEXT"+")")
    //execute the SQL command
    db?.execSQL(CREATE_USER_TABLE)
}

//onUpgrade is called when we upgrade our table
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
    db!!.execSQL("DROP TABLE IF EXISTS "+ TABLE_NAME)
    onCreate(db)
}

/**
 * Adds to database: CREATE
 */
fun addUserToFavorite(user: FavoriteModelClass): Long{
    //initialize the database that we want to write on
    val db = this.writableDatabase
    //contentValues carry the data that we want to put in the database
    val contentValues = ContentValues()
    //id is unecessary as it will automatically increment
    contentValues.put(KEY_USERNAME,user.username) //putting the username

    //success will return a long value
    val success = db.insert(TABLE_NAME,null,contentValues)
    db.close()
    return success
}

/**
 * Reading the data in database. Returns the user object: READ
 */
fun viewUserInFavorite(): ArrayList<FavoriteModelClass>{
    val userList: ArrayList<FavoriteModelClass> = ArrayList<FavoriteModelClass>()
    //selects ALL data, SQL command. Give me everything in the table!
    val selectQuery = "SELECT * FROM $TABLE_NAME"
    //initialize the database that we want to read on
    val db = this.readableDatabase
    //A SQL cursor retrieves data one row at a time
    var cursor: Cursor? = null

    try {
        cursor = db.rawQuery(selectQuery,null)
    } catch (e: SQLiteException){
        db.execSQL(selectQuery)
        return ArrayList()
    }

    //make variables to store data
    var id: Int
    var username: String

    //cursor moves to each entry one by one and retrieves data
    if (cursor.moveToFirst()){
        do {
            id = cursor.getInt(cursor.getColumnIndex(KEY_ID))
            username = cursor.getString(cursor.getColumnIndex(KEY_USERNAME))
            val user = FavoriteModelClass(id = id,username = username)
            userList.add(user)
        } while (cursor.moveToNext())
    }
    return userList
}

/**
 * Deletes a user from favorite: DELETE
 */
fun deleteUserInFavoriteByUsername(username: String): Int{
    //initialize the database that we want to delete on
    val db = this.writableDatabase
    //setup the container to show which user we want to delete
    val contentValues = ContentValues()
    contentValues.put(KEY_USERNAME,username)
    //Deleting Row where user is that
    val success = db.delete(TABLE_NAME, "$KEY_USERNAME=$username",null)
    db.close()
    return success
}

}

这是activity中的代码:

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityDetailUserBinding.inflate(layoutInflater)
    setContentView(binding.root)

    username = intent.getStringExtra(EXTRA_USERNAME).toString()
    binding.usernameSearchDetail.text = username

    setDetailData()

    val sectionsPagerAdapter = SectionsPagerAdapter(this)
    sectionsPagerAdapter.username = username
    val viewPager: ViewPager2 = binding.viewPager
    viewPager.adapter = sectionsPagerAdapter
    val tabs: TabLayout = binding.tabs
    TabLayoutMediator(tabs,viewPager){tab,position->
        tab.text = resources.getString(TAB_TITLES[position])
    }.attach()

    var statusFavorite = false
    favoriteIcon = binding.toolbar.buttonFavorite
    setStatusFavorite(statusFavorite)
    favoriteIcon.setOnClickListener{
        statusFavorite = !statusFavorite
        setStatusFavorite(statusFavorite)
        if (statusFavorite == true){
            addToFavorite()
        } else if (statusFavorite == false){
            deleteFromFavorite()
        }
    }
}

/**
 * Adds to favorite database
 */
private fun addToFavorite(){
    //initialize the database handler object
    val databaseHandler: DatabaseHandler = DatabaseHandler(this)
    val status = databaseHandler.addUserToFavorite(FavoriteModelClass(0,username))
    if (status>-1){
        Toast.makeText(this,"Added $username to favorites!",Toast.LENGTH_SHORT).show()
    } else {
        Toast.makeText(this,"Failed to add $username to favorites!",Toast.LENGTH_SHORT).show()
    }
}

/**
 * Deletes user from favorite database
 */
private fun deleteFromFavorite(){
    val databaseHandler: DatabaseHandler = DatabaseHandler(this)
    val status = databaseHandler.deleteUserInFavoriteByUsername(username)
    if (status>-1){
        Toast.makeText(this,"Removed $username from favorites!",Toast.LENGTH_SHORT).show()
    } else {
        Toast.makeText(this,"Failed to remove $username from favorites!",Toast.LENGTH_SHORT).show()
    }
}

private fun setStatusFavorite(statusFavorite: Boolean) {
    if (statusFavorite){
        favoriteIcon.setImageResource(R.drawable.ic_favorite)
    } else {
        favoriteIcon.setImageResource(R.drawable.ic_baseline_favorite_border_24)
    }

}

我陷入了困境。这是我的堆栈跟踪:

D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.dicoding.githubclone, PID: 10878
    android.database.sqlite.SQLiteException: no such column: brian (code 1 SQLITE_ERROR): , while compiling: DELETE FROM FavoriteTable WHERE username=brian
        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1102)
        at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:667)
        at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:590)
        at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:61)
        at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:33)
        at android.database.sqlite.SQLiteDatabase.delete(SQLiteDatabase.java:1727)
        at com.dicoding.githubclone.database.DatabaseHandler.deleteUserInFavoriteByUsername(DatabaseHandler.kt:100)
        at com.dicoding.githubclone.activity.DetailUserActivity.deleteFromFavorite(DetailUserActivity.kt:93)
        at com.dicoding.githubclone.activity.DetailUserActivity.access$deleteFromFavorite(DetailUserActivity.kt:26)
        at com.dicoding.githubclone.activity.DetailUserActivity$onCreate.onClick(DetailUserActivity.kt:69)
        at android.view.View.performClick(View.java:7500)
        at android.view.View.performClickInternal(View.java:7472)
        at android.view.View.access00(View.java:824)
        at android.view.View$PerformClick.run(View.java:28657)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:239)
        at android.app.ActivityThread.main(ActivityThread.java:8107)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:626)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1015)

请 post 你的堆栈跟踪。从代码来看,崩溃的一个明显原因是:

db.delete(TABLE_NAME, "$KEY_USERNAME=$username",null)

$username 在这里没有作为字符串文字引用,因此它被视为列名,您可能没有要删除的用户名的列名。

在 SQL 中,您将使用 'single quotes' 作为字符串文字,但使用变量会更好:

db.delete(TABLE_NAME, "$KEY_USERNAME=?", arrayOf(username))