Search code examples
javaandroidsqliteandroid-sqlite

Retreive/get row by id in SQLite, android studio doesn't work


I am trying to get data from my SQLite database in android studio. The method I am trying to invoke looks like:

 public Cursor getDataById(int id){
    SQLiteDatabase db=this.getWritableDatabase();
    String query="SELECT * FROM "+TABLE_NAME+" where receipt_id="+id;
    Cursor data=db.rawQuery(query,null);
    return data;
}

private void addComponentsAndData(){
        Cursor data=databaseService.getDataById(selectedId);

        System.out.println(data.getString(1));

        for(int i=0;i<8;i++){
            TextView textView=new TextView(this);
            switch(i){
                case 0:
                    textView.setText("ID tankowania: "+data.getString(i)+"\r\n");
                    break;
                case 1:
                    textView.setText("Data i czas tankowania: "+data.getString(i)+"\r\n");
                    break;
                case 2:
                    textView.setText("Rodzaj paliwa: "+data.getString(i)+"\r\n");
                    break;
                case 3:
                    textView.setText("Ilość paliwa: "+data.getString(i)+" l.\r\n");
                    break;
                case 4:
                    textView.setText("Kwota za litr: "+data.getString(i)+" zł\r\n");
                    break;
                case 5:
                    textView.setText("Kwota całości: "+data.getString(i)+" zł\r\n");
                    break;
                case 6:
                    textView.setText("Nazwa stacji: "+data.getString(i)+"\r\n");
                    break;
                case 7:
                    textView.setText("Numer rejestracyjny*: "+data.getString(i)+"\r\n");
                    break;
            }
            textView.setTextSize(20);
            linearLayout.addView(textView);
        }
}

Database looks like:

enter image description here Moreover, when i try to onvoke method, that returns all data it works:

public Cursor getData(){
    SQLiteDatabase db=this.getWritableDatabase();
    String query="SELECT * FROM "+TABLE_NAME;
    Cursor data=db.rawQuery(query,null);
    return data;
}

The exception i am getting looks like this:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app.recepitscannerapp, PID: 5410
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.app.recepitscannerapp/com.app.recepitscannerapp.HistorySelected}: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:223)
    at android.app.ActivityThread.main(ActivityThread.java:7656)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
 Caused by: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
    at android.database.AbstractCursor.checkPosition(AbstractCursor.java:514)
    at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:138)
    at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:52)
    at com.app.recepitscannerapp.HistorySelected.addComponentsAndData(HistorySelected.java:41)
    at com.app.recepitscannerapp.HistorySelected.onCreate(HistorySelected.java:35)
    at android.app.Activity.performCreate(Activity.java:8000)
    at android.app.Activity.performCreate(Activity.java:7984)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loop(Looper.java:223) 
    at android.app.ActivityThread.main(ActivityThread.java:7656) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 

Did anyone got such a problem before? I think I am making a simple mistake but i have already tried multiple things to repair it but it didn't work...


Solution

  • After you get the cursor data with:

    Cursor data=databaseService.getDataById(selectedId);
    

    the cursor's index is positioned before the 1st row of the row(s) that it contains.
    You must call moveToFirst() to set the index at the 1st row before you try to get any of the column values with data.getString():

    private void addComponentsAndData() {
        Cursor data=databaseService.getDataById(selectedId);
        if (!data.moveToFirst()) return;
        System.out.println(data.getString(1));
        ......................................
    }
    

    Also in the image I see that there are 7 columns in the table but the for loop in your code does 8 iterations to access 8 columns.
    You should change to:

    for(int i=0;i<7;i++) {
        .................
    }
    

    Also, the recommended way to pass parameters to rawQuery() is with ? placeholders and the values of the parameters as an array of strings:

    public Cursor getDataById(int id){
        SQLiteDatabase db=this.getWritableDatabase();
        String query="SELECT * FROM "+TABLE_NAME+" where receipt_id=?";
        Cursor data=db.rawQuery(query,new String[] {String.valueOf(id)});
        return data;
    }