我正在尝试使用 SQLite 数据库来存储回收站 View 的信息。我希望数据库根据描述只包含唯一的记录。我试图在创建数据库时将描述字段设置为唯一,但似乎没有帮助。相反,我决定创建一个函数来检查描述是否已存在于数据库中,然后插入包含此信息的新记录。在运行调试工具查看我哪里出错后,此功能工作正常。我认为错误出在 db.insert 函数中,该函数在 if 语句中似乎没有执行。感谢您的帮助。
附言我完全是 SQLite 的菜鸟,对它周围的行话不是很熟悉。
这是帮助处理数据库的类的部分代码
public class DataBaseHandler extends SQLiteOpenHelper {
private final Context context;
public DataBaseHandler(@Nullable Context context) {
super(context, Constants.DB_NAME, null, Constants.DB_VERSION);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_FOOD_TABLE = "CREATE TABLE " + Constants.TABLE_NAME + "("
+ Constants.KEY_ID + " INTEGER PRIMARY KEY,"
+ Constants.KEY_FOOD_ITEM + " INTEGER,"
+ Constants.KEY_PRICE + " TEXT,"
+ Constants.KEY_QTY_NUMBER + " INTEGER,"
+ Constants.KEY_DESCRIPTION + " TEXT,"
+ Constants.KEY_DATE_NAME + " LONG);";
db.execSQL(CREATE_FOOD_TABLE);
}
这是 hasObject 函数的代码:
public boolean hasObject(String foodCode) {
SQLiteDatabase db = getWritableDatabase();
String selectString = "SELECT * FROM " + Constants.TABLE_NAME + " WHERE " + Constants.KEY_DESCRIPTION + " =?";
// Add the String you are searching by here.
// Put it in an array to avoid an unrecognized token error
Cursor cursor = db.rawQuery(selectString, new String[] {foodCode});
boolean hasObject = false;
if(cursor.moveToFirst()){
hasObject = true;
}
cursor.close();
db.close();
return hasObject;
}
常量在单独的类中定义为静态最终。
这是我的代码中存在问题的地方。
public void addItem(Item item) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(Constants.KEY_FOOD_ITEM, item.getItemName());
values.put(Constants.KEY_PRICE, item.getPrice_double());
values.put(Constants.KEY_QTY_NUMBER, item.getItemQuantity());
values.put(Constants.KEY_DESCRIPTION, item.getDescription());
values.put(Constants.KEY_DATE_NAME,
java.lang.System.currentTimeMillis());//timestamp of the system
// db.insert(Constants.TABLE_NAME, null, values);
// Log.d("DBHandler", "added Item: ");
//Check if the record already exists in the database
if(!hasObject(item.getDescription())){
//Insert the row
db.insert(Constants.TABLE_NAME, null, values); // This is not running as planned
Log.d("DBHandler", "added Item: ");
}
else {
//Don't insert the row
Log.d("DBHandler", "Item exists");
}
}
正如您所注意到的,我尝试按原样运行 db.insert 函数,而不检查记录是否已存在于数据库中,并且运行正常。 但是,如果我继续添加记录,无论它们是否在数据库中,都会有太多重复项,这会弄乱回收站 View 。
这里调用了 additem 函数:
databaseHandler= new DataBaseHandler(this);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
itemList= new ArrayList<>();
//tempitemlist = new ArrayList<>();
//Get items from Firebase
mfoodRef.addValueEventListener(new ValueEventListener() {
//Will run everytime there is an update to the condition value in the database
//So this will run when the .setValue function runs in the button onClickListener classes
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
//tempitemlist.clear();
Iterable<DataSnapshot> databaseMenu = dataSnapshot.getChildren();
for (DataSnapshot data:databaseMenu){
Menu tempMenu = data.getValue(Menu.class);
Item tempItem = new Item(tempMenu.getFoodName(),tempMenu.getFoodCode(),tempMenu.getFoodPrice());
//itemList.add(tempItem);
databaseHandler.addItem(tempItem);
}
}
// In case we run into any errors
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
是的,我正在使用我的 Firebase 实时数据库中的信息来更新 onDataChange 方法中的数据库处理程序的内容。这就是为什么我需要在插入新记录时检查重复项。
编辑:
这是我在调试日志中发现的:
Process: com.example.vendorwrecycler, PID: 12882
java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/user/0/com.example.vendorwrecycler/databases/foodList
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:57)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1567)
at android.database.sqlite.SQLiteDatabase.insertOrThrow(SQLiteDatabase.java:1494)
at com.example.vendorwrecycler.data.DataBaseHandler.addItem(DataBaseHandler.java:68)
at com.example.vendorwrecycler.ListActivity.saveItem(ListActivity.java:184)
at com.example.vendorwrecycler.ListActivity.access$500(ListActivity.java:34)
at com.example.vendorwrecycler.ListActivity$4.onClick(ListActivity.java:159)
at android.view.View.performClick(View.java:7125)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access$3500(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
也许这可能与 IllegalStateException 有关?
最佳答案
您正在尝试对关闭的 DB
实例执行操作。尝试在 if
语句中移动 SQLiteDatabase db = getWritableDatabase();
。
if(!hasObject(item.getDescription())){
//Insert the row
SQLiteDatabase db = getWritableDatabase();
db.insert(Constants.TABLE_NAME, null, values);
Log.d("DBHandler", "added Item: ");
}
else {
//Don't insert the row
Log.d("DBHandler", "Item exists");
}
您在 hasObject
函数中关闭了 DB
的连接。
关于android - SQLite : db. 插入在 if 语句中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59171783/