当我试图从 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))
所以我正在创建一个 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))