SQLite:db.insert在if语句中不起作用

时间:2019-12-04 08:28:15

标签: android android-sqlite

我正在尝试使用SQLite数据库存储回收者视图的信息。我希望数据库根据其描述仅包含唯一记录。创建数据库时,我试图将描述字段设置为唯一,但这似乎无济于事。相反,我决定创建一个函数来检查描述是否已经存在于数据库中,然后使用该信息插入新记录。运行调试工具查看我出了问题的地方后,此功能可以正常工作。我认为错误在于db.insert函数,该函数似乎在if语句内部时未执行。任何帮助表示赞赏。

P.S。我对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;
    }

在单独的类中将这些常量定义为静态的final。

这是存在问题的我的代码。

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函数,而不检查数据库中是否已存在该记录,并且它工作正常。 但是,如果我继续添加记录,无论它们是否在数据库中,都会有太多重复项,这会弄乱回收者视图。

在这里调用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有关?

2 个答案:

答案 0 :(得分:1)

您正在尝试在封闭的DB实例上执行操作。尝试在SQLiteDatabase db = getWritableDatabase();语句内移动if

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");
}

您在DB函数中关闭了hasObject的连接。

答案 1 :(得分:0)

tempItem变量中没有Item tempItem = new Item(tempMenu.getFoodName(),tempMenu.getFoodCode(),tempMenu.getFoodPrice());

item.getDescription()

因此tempItem必须为

记录所有{{1}}对象变量,并确保所有变量都不为null或为空。

希望这会有所帮助