简体   繁体   English

无法从具有 1 行 9 列的 CursorWindow 读取第 0 行第 -1 列

[英]Failed to read row 0, column -1 from a CursorWindow which has 1 rows, 9 columns

I'm trying to load data from my table in sqlite Database to my ExpandableListView inside my activity.我正在尝试将我在 sqlite 数据库中的表中的数据加载到我的活动中的 ExpandableListView。 I followed the answer from this question Android ExpandableListView and SQLite Database .我遵循了这个问题Android ExpandableListView and SQLite Database的答案。

My parent list will show MVP_INDUSTRY_TYPE Column depends on date Selected, My child list will show MVP_BRCH_CODE_NAME and MVP_BRCH_ADDRESS.我的父列表将显示 MVP_INDUSTRY_TYPE 列取决于所选日期,我的子列表将显示 MVP_BRCH_CODE_NAME 和 MVP_BRCH_ADDRESS。

DatabaseHelper.数据库助手。 java爪哇

package com.example.spmapp;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;


public class DataBaseHelper extends SQLiteOpenHelper {

    public static final String MVP_TBL = "MVP_tbl";
    public static final String MVP_BRCH_CODE_NAME = "MVP_BRCH_CODE_NAME";
    public static final String MVP_ID = "MVP_ID";
    public static final String MVP_BRCH_ADDRESS = "MVP_BRCH_ADDRESS";
    public static final String MVP_AREA = "AREA";
    public static final String MVP_AREA_CODE = "AREA_CODE";
    public static final String MVP_INDUSTRY_TYPE = "MVP_INDUSTRY_TYPE";
    public static final String token = "TOKEN";
    public static final String MVP_DATE = "SCHEDULED_DATE";
    public static final String MVP_CLASS_ID = "MVP_CLASS_ID";



    public DataBaseHelper(@Nullable Context context) {
        super(context, "taggedList.db", null, 1);

    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        String createMVPVirtualTableStatement = "CREATE VIRTUAL TABLE IF NOT EXISTS " + MVP_TBL + " USING FTS3(" + MVP_BRCH_CODE_NAME + ", " + MVP_ID + " , " + MVP_BRCH_ADDRESS + ", " + MVP_AREA + ", " + MVP_AREA_CODE + ", " + MVP_INDUSTRY_TYPE + ", " + token + ", " + MVP_DATE + ", " + MVP_CLASS_ID + ")";
        sqLiteDatabase.execSQL(createMVPVirtualTableStatement);

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        onCreate(sqLiteDatabase);
    }
    public Cursor getSelectedParentMVPDate(String txtMVPDate){
        SQLiteDatabase db = this.getWritableDatabase();
        String query = "Select * from "+MVP_TBL+" WHERE " +MVP_DATE+ " LIKE '%"+txtMVPDate+"%' LIMIT 50";
        return db.rawQuery(query, null);
    }
    public Cursor getSelectedChildMVPDate(String MVPIndustry){
        SQLiteDatabase db = this.getWritableDatabase();
        String query = "Select * from "+MVP_TBL+" WHERE " +MVP_INDUSTRY_TYPE+ " LIKE '%"+MVPIndustry+"%' LIMIT 50";
        return db.rawQuery(query, null);
    }

}

MasterVisitPlan.java MasterVisitPlan.java

public class MasterVisitPlan extends AppCompatActivity implements AdapterView.OnItemSelectedListener,CalendarAdapter.OnItemListener {

    private boolean isBackPressedOnce = false;

    public static String email;
    public static String VisitDate;
    public static String ItemBrnchCodeName;
    public static String mrCode;
    public static String ClassID;
    private static String token;
    private static String bearerToken;
    public static int counterVisit;
    private RecyclerView calendarRecyclerView;
    private LocalDate selectedDate;
    private TextView monthYearText;


    TextView empName, empPos, date;

    GoogleSignInClient mGoogleSignInClient;

    DrawerLayout drawerLayout;

    ImageView gps, empPhoto;

    ConstraintLayout calendar;

    DataBaseHelper dataBaseHelper;
    private Cursor mGroupsCursor; // cursor for list of groups (list top nodes)
    private int mGroupIdColumnIndex;
    private MyExpandableListAdapter mAdapter;

    SimpleCursorAdapter sca;
    Cursor csr;
    SearchView searchView;
    ListView Searchlstview;


    @Override
    protected void onCreate(Bundle savedIntanceState) {
        super.onCreate(savedIntanceState);
        setContentView(R.layout.activity_master_visit_plan);
        initWidgets();
        selectedDate = LocalDate.now();
        setMonthView();
        setOrRefreshListView();
        getCurrentDate();

        dataBaseHelper = new DataBaseHelper(MasterVisitPlan.this);
        fillMVPdata();  
    }

    private void fillMVPdata(){
        mGroupsCursor = dataBaseHelper.getSelectedParentMVPDate(date.getText().toString());
        startManagingCursor(mGroupsCursor);
        mGroupsCursor.moveToFirst();


        ExpandableListView Selectedlstview = (ExpandableListView) findViewById(R.id.MVPListitem);
        mAdapter = new MyExpandableListAdapter(mGroupsCursor, this,

                R.layout.mvp_list_parent,
                R.layout.mvp_list_child,
                new String[] {DataBaseHelper.MVP_INDUSTRY_TYPE},
                new int[] {R.id.txtMVPParent},
                new String[] {DataBaseHelper.MVP_BRCH_CODE_NAME, DataBaseHelper.MVP_BRCH_ADDRESS},
                new int[] {R.id.txtviewBrnchCodeName, R.id.txtviewBrchAddr});

                Selectedlstview.setAdapter(mAdapter);

    }
    public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {
        public MyExpandableListAdapter(Cursor cursor, Context context,int groupLayout, int childLayout, String[] groupFrom,
                                       int[] groupTo, String[] childrenFrom, int[] childrenTo) {
            super(context, cursor, groupLayout, groupFrom, groupTo,
                    childLayout, childrenFrom, childrenTo);
        }

        @Override
        protected Cursor getChildrenCursor(Cursor cursor) {
            @SuppressLint("Range") Cursor childCursor = dataBaseHelper.getSelectedChildMVPDate(cursor.getString(cursor.getColumnIndex("MVP_INDUSTRY_TYPE")));
            startManagingCursor(childCursor);
            childCursor.moveToFirst();
            return childCursor;
        }
    }
}

Column -1 indicates that the column is not in the Cursor when using the getColumnIndex method. Column -1表示使用getColumnIndex方法时该列不在 Cursor 中。

As the only occurrence of the method, in the provided code, is in the getSelectedChildMVPDate method in the DatabaseHelper class, then that must be where the issue is taking place.由于该方法在所提供的代码中唯一出现在 DatabaseHelper 类中的getSelectedChildMVPDate方法中,因此这一定是问题发生的地方。

Replicating the essentials of your code with an additional method in DataBaseHelper class :-使用DataBaseHelper类中的附加方法复制代码的基本要素:-

public void insertMVPTBLRow(String branchCodeName, long id, String address, String area, String areacode, String industryType, String tkn, String date, String classId) {
    ContentValues cv = new ContentValues();
    cv.put(MVP_BRCH_CODE_NAME,branchCodeName);
    cv.put(MVP_ID,id);
    cv.put(MVP_BRCH_ADDRESS,address);
    cv.put(MVP_AREA,area);
    cv.put(MVP_AREA_CODE,areacode);
    cv.put(MVP_INDUSTRY_TYPE,industryType);
    cv.put(token,tkn);
    cv.put(MVP_DATE,date);
    cv.put(MVP_CLASS_ID,classId);
    this.getWritableDatabase().insert(MVP_TBL,null,cv);
}

and then using the following code in an activity:-然后在活动中使用以下代码:-

    dataBaseHelper = new DataBaseHelper(this);
    dataBaseHelper.getWritableDatabase().delete(DataBaseHelper.MVP_TBL,null,null);
    dataBaseHelper.insertMVPTBLRow("B1",100,"StreetX","Area1","A001","I001","tkn001",String.valueOf(System.currentTimeMillis()),"CLASS1");
    dataBaseHelper.insertMVPTBLRow("B1",101,"StreetX","Area1","A001","I001","tkn002",String.valueOf(System.currentTimeMillis()),"CLASS1");
    mGroupsCursor = dataBaseHelper.getSelectedParentMVPDate("");
    startManagingCursor(mGroupsCursor);
    mGroupsCursor.moveToFirst();
    Cursor cursor = mGroupsCursor;
    @SuppressLint("Range") Cursor childCursor = dataBaseHelper.getSelectedChildMVPDate(cursor.getString(cursor.getColumnIndex("MVP_INDUSTRY_TYPE")));
    startManagingCursor(childCursor);
    childCursor.moveToFirst();
    DatabaseUtils.dumpCursor(mGroupsCursor);
    DatabaseUtils.dumpCursor(childCursor);
  • Note empty string passed so all rows are extracted.注意传递了空字符串,因此提取了所有行。

Results in a successful run with the Log including:-使用日志成功运行的结果包括:-

2022-06-15 10:55:26.892 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@2caa87e
2022-06-15 10:55:26.893 I/System.out: 0 {
2022-06-15 10:55:26.893 I/System.out:    MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.893 I/System.out:    MVP_ID=100
2022-06-15 10:55:26.893 I/System.out:    MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.893 I/System.out:    AREA=Area1
2022-06-15 10:55:26.893 I/System.out:    AREA_CODE=A001
2022-06-15 10:55:26.893 I/System.out:    MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.893 I/System.out:    TOKEN=tkn001
2022-06-15 10:55:26.893 I/System.out:    SCHEDULED_DATE=1655254526888
2022-06-15 10:55:26.893 I/System.out:    MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.893 I/System.out: }
2022-06-15 10:55:26.893 I/System.out: 1 {
2022-06-15 10:55:26.893 I/System.out:    MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.893 I/System.out:    MVP_ID=101
2022-06-15 10:55:26.893 I/System.out:    MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.894 I/System.out:    AREA=Area1
2022-06-15 10:55:26.894 I/System.out:    AREA_CODE=A001
2022-06-15 10:55:26.894 I/System.out:    MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.894 I/System.out:    TOKEN=tkn002
2022-06-15 10:55:26.895 I/System.out:    SCHEDULED_DATE=1655254526889
2022-06-15 10:55:26.895 I/System.out:    MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.895 I/System.out: }
2022-06-15 10:55:26.895 I/System.out: <<<<<
2022-06-15 10:55:26.895 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@f1451df
2022-06-15 10:55:26.895 I/System.out: 0 {
2022-06-15 10:55:26.895 I/System.out:    MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.895 I/System.out:    MVP_ID=100
2022-06-15 10:55:26.895 I/System.out:    MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.895 I/System.out:    AREA=Area1
2022-06-15 10:55:26.895 I/System.out:    AREA_CODE=A001
2022-06-15 10:55:26.895 I/System.out:    MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.895 I/System.out:    TOKEN=tkn001
2022-06-15 10:55:26.896 I/System.out:    SCHEDULED_DATE=1655254526888
2022-06-15 10:55:26.896 I/System.out:    MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.896 I/System.out: }
2022-06-15 10:55:26.896 I/System.out: 1 {
2022-06-15 10:55:26.896 I/System.out:    MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.896 I/System.out:    MVP_ID=101
2022-06-15 10:55:26.896 I/System.out:    MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.896 I/System.out:    AREA=Area1
2022-06-15 10:55:26.896 I/System.out:    AREA_CODE=A001
2022-06-15 10:55:26.896 I/System.out:    MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.896 I/System.out:    TOKEN=tkn002
2022-06-15 10:55:26.896 I/System.out:    SCHEDULED_DATE=1655254526889
2022-06-15 10:55:26.896 I/System.out:    MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.896 I/System.out: }
2022-06-15 10:55:26.897 I/System.out: <<<<<

Now considering the message Failed to read row 0, column -1 from a CursorWindow which has 1 rows, 9 columns现在考虑消息Failed to read row 0, column -1 from a CursorWindow which has 1 rows, 9 columns

Then然后

  1. The Cursor is positioned at row 0 (not at row -1 which is before the first row)光标位于第 0 行(不是在第一行之前的第 -1 行)

  2. Of the 9 columns the specified column has not been found.在 9 列中,未找到指定的列。

  3. From the dump of both cursors there are 9 columns.从两个游标的转储中有 9 列。

  4. getColumnIndex has a bug in that it is case sensitive getColumnIndex有一个错误,它区分大小写

  5. However, as the above works, this is not an issue with your code although I would strongly suggest changing your code to use cursor.getColumnIndex(/*"MVP_INDUSTRY_TYPE" <<<<< CHANGED*/ DataBaseHelper.MVP_INDUSTRY_TYPE) (obviously the comment could be omitted)但是,如上所述,这不是您的代码的问题,尽管我强烈建议您更改代码以使用cursor.getColumnIndex(/*"MVP_INDUSTRY_TYPE" <<<<< CHANGED*/ DataBaseHelper.MVP_INDUSTRY_TYPE) (显然是评论可以省略)

  6. As such the issue is either:-因此,问题是: -

    1. Elsewhere in your code, or在您的代码中的其他地方,或
    2. That the columns name coded/used in the onCreate method have been changed BUT that they have not been applied. onCreate方法中编码/使用的列名称已更改但尚未应用。
      • The onCreate method runs once and only once when the database is created. onCreate方法只在创建数据库时运行一次。
      • The onCreate method will never automatically run again unless the database is deleted.除非删除数据库,否则onCreate方法将永远不会自动再次运行。
      • Uninstalling the App will delete the database BUT will lose any existing data.卸载应用程序将删除数据库但将丢失任何现有数据。
      • If you need to retain existing data, then you need to rebuild the table with the correct column name, noting that virtual tables has restrictions.如果需要保留现有数据,则需要使用正确的列名重建表,注意虚拟表有限制。 You would probably need to utilise the onOpen method and within the method:-您可能需要使用onOpen方法并在该方法内:-
        • create the new table BUT with a different name使用不同的名称创建新表

        • populate the newly created table with the data from the orginal table使用原始表中的数据填充新创建的表

        • drop the original table删除原始表

        • rename the newly created table with the original/required name用原始/必需的名称重命名新创建的表

        • However, as onOpen runs whenever the database is opened you would want to limit this to only do the above when required (ie when there is a naming discrepancy).然而,当打开数据库时onOpen就会运行,您可能希望将其限制为仅在需要时执行上述操作(即,当存在命名差异时)。 The following onOPen method could be the basis以下onOPen方法可以作为基础

:- :-

@Override
public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    Log.d("ONOPEN","ON OPEN INVOKED");
    Cursor checkit = db.query(MVP_TBL,null,null,null,null,null,null,"1");
    boolean needToProceed = false;
    for (String s: new String[]{MVP_AREA,MVP_AREA_CODE,MVP_DATE,MVP_ID,MVP_BRCH_ADDRESS,MVP_BRCH_CODE_NAME,MVP_CLASS_ID,MVP_INDUSTRY_TYPE,token}) {
        boolean found = false;
        for (String cc: checkit.getColumnNames()) {
            if (cc.equals(s)) {
                Log.d("ONOPEN","Column " + cc + " matched " + s);
                found = true;
                break;
            }
        }
        if (!found) {
            Log.d("ONOPEN","!!!!COLUMN " + s + " NOT MATCHED.!!!!" );
            needToProceed = true;
            break;
        }
    }
    if (!needToProceed) return;
    Log.d("ONOPEN","PROCEEDING WITH RECREATION OF " + MVP_TBL +" TABLE.");
    String renamed = "ORIGINAL_" + MVP_TBL;
    db.execSQL("ALTER TABLE " + MVP_TBL + " RENAME TO " + renamed + ";");
    onCreate(db);
    db.execSQL("INSERT INTO " + renamed + " SELECT * FROM " + MVP_TBL);
    db.execSQL("DROP TABLE IF EXISTS " + MVP_TBL);
    db.execSQL("ALTER TABLE " + renamed + " RENAME TO " + MVP_TBL);
}
  • The Logging should be removed if distributing the App.如果分发应用程序,应删除日志记录。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM