Android SQLiteStatement Insert; Последующие звонки не удаются - PullRequest
0 голосов
/ 29 марта 2011

Я пытаюсь вставить строки в базу данных SQLite в Android. Вызов для вставки записи в мою БД выглядит так: DataHelper.insertChild (context, child). Моя цель - обернуть функциональность в статически называемые функции, которые обрабатывают все мелочи. Сначала позвольте мне поделиться с вами своим кодом.

Я делаю это с помощью статических методов:

private static SQLiteDatabase prepareChildDatabase(Context context) {
    Log.d(TAG, "DB: prepareChildDatabase");
    OpenHelper openHelper = new OpenHelper(context);
    return openHelper.getWritableDatabase();
}

Тогда я делаю свою вставку:

    public static long insertChild(Context context, Child child) {
    Log.d(TAG, "DB: insertChild");

    SQLiteDatabase db = prepareChildDatabase(context);
    SQLiteStatement insertStmt = db.compileStatement(INSERT);
    insertStmt.bindLong(1, child.getBirthday().getTime());

    // These are optional
    if(child.getName() != null) {
        insertStmt.bindString(2, child.getName());
    } else {
        insertStmt.bindNull(2);
    }

    if(child.getPhoto() != null) {
        String photoUri = child.getPhoto().toString();
        insertStmt.bindString(3, photoUri);
    } else {
        insertStmt.bindNull(3);
    }

    final long id = insertStmt.executeInsert();

    // insertStmt.clearBindings(); // Not sure this is necessary
    insertStmt.close();
    db.close();

    return id;
}

Для справок, мой OpenHelper здесь:

    private static class OpenHelper extends SQLiteOpenHelper {

    OpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.d(TAG, "DB: OpenHelper: onCreate: " + CREATE_CHILDREN_TABLE);
        db.execSQL(CREATE_CHILDREN_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
    }
}

И, наконец, переменные, операторы и таблица:

private static final String TABLE_NAME = "children";
private static final String COL_NAME = "name";
private static final String COL_BDAY = "birthday";
private static final String COL_PHOTO = "photo";

private static final String INSERT = "insert into " 
    + TABLE_NAME + " (" 
        + COL_BDAY + ", "
        + COL_NAME + ", " 
        + COL_PHOTO + ") values (?, ?, ?)";

private static final String UPDATE = "update " 
    + TABLE_NAME + "set "
        + COL_BDAY + " = ?, "
        + COL_NAME + " = ?, "
        + COL_PHOTO + " = ?) WHERE "
        + BaseColumns._ID + " = ?";

private static final String CREATE_CHILDREN_TABLE = 
    "CREATE TABLE " + TABLE_NAME + " ("
        + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
        + COL_BDAY + " INTEGER NOT NULL, "
        + COL_NAME + " TEXT NULL, "
        + COL_PHOTO + " TEXT NULL)";

Так что происходит, когда я первый раз так называю, все работает нормально. Вставка работает, данные есть, и я могу экспортировать БД с устройства в мой браузер SQLite. Последующие вызовы insertChild (...) нарушают работу БД. Открытие не работает, так как SQLiteBrowser не показывает таблиц или строк, а открытие его в текстовом редакторе показывает некоторые вещи; Я предполагаю, что БД повреждена. Больше строк не вставляется, и я не могу прочитать это. Никаких ошибок не выдается.

Я предполагаю, что здесь происходит одна из двух вещей. Во-первых, мои дескрипторы не открываются / закрываются правильно, и некоторые ссылки где-то блокируются последующими вызовами. Во-вторых, мое понимание подготовленных утверждений неверно. Дело в том, что я смотрю на код, и он кажется нормальным. Откройте базу данных, свяжите с подготовленным оператором, выполните, закройте оператор, закройте базу данных.

Кто-нибудь готов помочь мне с этим? Я регистрируюсь, ищу исключения и пробую что-то, но ничего не получается. Думаю, я просто пропустил небольшую деталь. Это или я схожу с ума.

Спасибо

Mike

Обновление

Я обратил свое внимание на потоки, потому что проблема не воспроизводится на моем эмуляторе. Проверьте эти ссылки:

http://www.kagii.com/journal/2010/9/10/android-sqlite-locking.html

Приложение Android sqlite принудительно закрывается на устройстве

Каковы лучшие практики для SQLite на Android?

Ответы [ 3 ]

0 голосов
/ 29 марта 2011

Прежде всего .... когда вы работаете с экземпляром БД или экземпляром курсора или экземпляром Steatment (или чем-то, что нужно закрыть в конце), используйте следующий синтаксис:

    SQLiteOpenHelper db;
    try{
        db = myDB.open();//open the database here
        //do whatever you want with the DB instance
    }finally{
        if(db != null){
            db.close();
        }
    }

Если в середине процесса будет сгенерировано исключение, вы закроете БД.

Удалите этот финал

final long id = insertStmt.executeInsert();

И для лучшей отладки поместите в эту попытку ловушку/ наконец, и вы лучше увидите, что происходит.

0 голосов
/ 06 апреля 2011

Похоже, что у устройства, на котором я тестирую, есть проблемы с разрешениями и записью файлов базы данных.Проблема в том, что БД изначально создается, вставляются строки, а затем блокируется.Последующие вызовы повреждают его.

Это, вероятно, результат рутирования устройства.Или, возможно, потому что UID пакетов был изменен.

0 голосов
/ 29 марта 2011

Вы должны открывать соединение всегда, когда вам это нужно. Или откройте его, прежде чем делать ВСЕ вставки перед закрытием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...