【问题标题】:SQLitedatabase not inserting id for lollipopSQLitedatabase没有为棒棒糖插入ID
【发布时间】:2015-02-23 10:39:57
【问题描述】:

我有以下代码在数据库中插入 contentValues。我使用 SQLitedatabase 方法 insert() 在数据库中插入值,如下所示:

    public static final String ID = "id";
    public boolean replaceOrUpdate(DBListener dbListener,final String sTable, ContentValues[] contentValues,String tag) {
    this.mDbListener=dbListener;

    if(mDatabase == null) {
        openDB();
    }
    mDatabase.beginTransaction();
    try {
        int count = contentValues.length;
        for (int i=0; i<count;i++) {
            ContentValues value = contentValues[i];
            long id = mDatabase.replaceOrThrow(sTable,null,value);
        }
        mDatabase.setTransactionSuccessful();
        mDbListener.onCompleteInsertion(tag);
    }catch (Exception e) {
        Log.v("Exception = " , " " + e.toString());
        e.printStackTrace();
    }finally {
        mDatabase.endTransaction();
    }
    return true;
}


public ArrayList<String> getAllPlacesIDs()
{
    ArrayList<String> ids = new ArrayList<String>();
    try
    {
        if(mDatabase==null || !mDatabase.isOpen())
        {
            openDB();
        }
        String query="SELECT "+DBUtil.ID+" FROM "+TABLE_MERCHANT_STORES;
        Cursor  cursor = mDatabase.rawQuery(query,null);
        for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext())
        {
            ids.add(cursor.getString(cursor.getColumnIndex(DBUtil.ID)));
        }
        cursor.close();
    }catch(SQLException sqx)
    {
        sqx.printStackTrace();
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
    finally
    {

    }
    return ids;

}

创建表如下:

db.execSQL("CREATE TABLE IF NOT EXISTS "+
            TABLE_MERCHANT_STORES +" ("+
            AUTO_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "+
            DBUtil.ID       +" INTEGER NOT NULL UNIQUE, "+...)

此代码在棒棒糖之前的设备上运行良好,但插入在棒棒糖上无法正常工作。它似乎卡在某些值上并继续在表中插入缺失值。插入后,当我打印所有值时,它们以升序显示,缺少一些中间值。表中存储的id值为

1 2 3 4 5 7 11 13 14 15 16 17 19

而在棒棒糖前插入(预期)的值是:

514 533 531 312 434 162 253 252 151 344 153 160 658

在棒棒糖设备上看到的错误模式是,当在表中插入一个 id 时,只要它接收到的下一个 id 不大于查询,似乎查询会继续插入最后一个最大 ID 和当前最大 id 之间的间隙比插入的当前 id。这是棒棒糖sqlite中的错误吗?还是我的设备特有的东西?应用程序中没有实现这样的逻辑。我该如何纠正?是因为使用的字符串是 id 吗?它在棒棒糖之前的设备上运行良好,但在棒棒糖上运行错误。

编辑:

我添加值的方式如下:

private void insertIntoDB() {
    int count = jsonArray.length();
    ContentValues[] values = new ContentValues[count];

    for(int i=0;i<count;i++){
        JSONObject storeObject=jsonArray.getJSONObject(i);
        if(storeObject!=null){
            ContentValues value=new ContentValues();
            value.put(DBUtil.ID, storeObject.getInt("id"));
            mArrId.add(storeObject.getInt("id")+"");
            value.put("place_parent", storeObject.getInt("place_parent"));
        }
    }
    Cursor c1=new MylocalCursorLoader(mContext, "Delete from " + DBUtil.TABLE_MERCHANT_STORES).loadInBackground();
                if(c1!=null){
                    DBUtil dbUtil = DBUtil.getInstance(mContext.getApplicationContext());
                    dbUtil.replaceOrUpdate(this, DBUtil.TABLE_MERCHANT_STORES, values,"merchant-stores");
                    mProgess.setVisibility(View.VISIBLE);
                }
}

MyLocalCursorLoader 是一个扩展 CursorLoader 的类。 storeObject.getInt("id") 的值按

的顺序排列

514 533 531 312 434 162 253 252 151 344 153 160 658

【问题讨论】:

    标签: android mysql sqlite


    【解决方案1】:

    如果没有看到您的所有代码,问题似乎与将 ContentValues[] 传递给您的 replaceOrUpdate() 方法有关。

    您可以在方法中的循环中添加一条日志行来验证是否是这种情况:

        for (int i=0; i<count;i++) {
            ContentValues value = contentValues[i];
            long id = mDatabase.replaceOrThrow(sTable,null,value);
            // Check output between Lollipop and earlier platform versions
            Log.v("DBUtil", "replaceOrThrow() returned " + id + "; value=" + value.toString());
        }
    

    否则,如果您可以在 ContentValues[] 被填充的位置发布代码,这可能会帮助您更快地获得更直接的答案。

    【讨论】:

    • 我已经打印了日志并检查了它,replaceOrThrow() 从 1....786 开始按顺序输出 id,而 value.get(DBUtil.ID).toString() 打印出的值需要插入 514, 533, 531, 312, 434, 162, 253, 252, 151,..., (随机顺序的整数集合,每个商店唯一的房间号)
    • 您是否将AUTO_ID 列包含在您的ContentValues 中?如果是这样,如果您按照我的回答在循环中记录相关值,它们是否与您在之后查询表时看到的一致?换句话说,也许replaceOrThrow()AUTO_ID 的值存储在ID 列中?我还注意到您将DBUtil.ID 定义为小写"id",但您的CREATE TABLE 中的列名是大写的;如果我没记错的话,Cursor.getColumnIndex() 区分大小写,所以这也可能导致一些问题。
    • ID 是一个值为“id”的全局变量。您可以通过 DBUtil.ID 在其他类中访问它。 AUTO_ID 列是自动递增的,因此不包含在 ContentValues 中。
    • 但是您使用此变量将小写的id 作为列名传递给区分大小写的Cursor.getColumnIndex(),并且您的CREATE TABLE 语句中的列名是硬编码的大写ID。这可能会导致一些问题。关于AUTO_IDreplaceOrThrow() 方法需要一个主键才能替换现有行;如果您在主键列上使用AUTOINCREMENT,那么insertOrThrow() 是更合适的选项。
    • 用于创建表的ID又是一个全局变量。它已经在问题中进行了更改。如果在创建表列时出现问题,那么它将不会在棒棒糖之前的设备上运行
    【解决方案2】:

    我找到了解决方案。如果我在表中创建 DBUtil.ID 属性时删除了 UNIQUE,那么它可以正常工作。我仍然不知道这个的确切原因。如果有人能澄清这种荒谬行为的原因,将不胜感激。

    【讨论】:

      猜你喜欢
      • 2015-08-12
      • 1970-01-01
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      • 2015-03-12
      • 2016-07-30
      • 2016-12-26
      • 2016-02-04
      相关资源
      最近更新 更多