Страница 2 из 3

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 27 сен 2013, 11:01
vgavt
Добрый день.
не подскажите почему при обновлении всех raw в таблице метод возвращает ноль(хотя колонка заполняется данными)?
db.execSQL("alter table " + DATABASE_TABLE + " add column "
+ KEY_PIC + " text;");
db.update(DATABASE_TABLE, updateCV, null, null);
db.update возвращает 0 даже если 10 строчек обновлены.

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 02 дек 2013, 14:30
Digetix
Как такое получение данных правильно оформить в транзакцию?

Код: Выделить всё

query = new ParseQuery("mens");
                   query.setLimit(50);             
                    query.findInBackground(new FindCallback() {
                    public void done(List<ParseObject> mens, ParseException e) {
                      if (e == null) {
                            for ( int i = 0; i < 50; i++) {    
                                
                                 stGet = mens.get(i).getString("Str");                                 
                                 cv.put("email", stGet);

                                 long rowID = db.insert("mytable", null, cv);
                                 Toast.makeText(getApplicationContext(), "Вставка ID = " + rowID, Toast.LENGTH_SHORT).show();
                                }                
                         } 
                      }
                     }); 

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 02 дек 2013, 16:42
Foenix
не получение, а вставку
Просто до цикла for стартани ее, а после цикла - завершай.
А вообще я просто объект передаю методу хэлпера и там стартую транзакцию и разбираю объект на части-вставки.

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 02 дек 2013, 17:40
Digetix
Foenix писал(а): Просто до цикла for стартани ее, а после цикла - завершай.

Код: Выделить всё

query = new ParseQuery("mens"); 
                   query.setLimit(50);              
                    query.findInBackground(new FindCallback() { 
                    public void done(List<ParseObject> mens, ParseException e) { 
                      if (e == null) { 
                          db.beginTransaction();
                            for ( int i = 0; i < 50; i++) {     
                                 
                                 stGet = mens.get(i).getString("Str");                                  
                                 cv.put("email", stGet); 
 
                                 long rowID = db.insert("mytable", null, cv); 
                                 db.endTransaction();
                                 Toast.makeText(getApplicationContext(), "Вставка ID = " + rowID, Toast.LENGTH_SHORT).show(); 
                                }                 
                         }  
                      } 
                     });  
Я вас правильно понял?
И тут же есть вопрос по уроку: в уроке везде идёт db.beginTransaction(); и db.endTransaction();, а в конце написано, что нужно использовать finally, как правильно?

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 02 дек 2013, 17:48
Foenix
неправильно. Финишировать нужно в finaly и ЗА циклом, когда уже все записи вставлены.

Код: Выделить всё

mDatabase.beginTransaction();
try{
  //тут весь твой цикл целиком
  mDatabase.setTransactionSuccessful();
  }catch(Exception e){
    //Обрабатываем ошибку
     }
finally {
               mDatabase.endTransaction();


        }
}

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 02 дек 2013, 23:21
Digetix
Спасибо, всё работает

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 16 янв 2014, 23:36
TittTitov
Здравствуйте!

Объясните, пожалуйста, откуда и какие данные вставляет транзакция в таблицу в этом примере:
db.beginTransaction();
insert(db, "mytable", "val1");
- это просто вставляется пустая строка с id=1?
Спасибо!

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 16 янв 2014, 23:59
Foenix
немного поправлю.. транзакция никуда и ничего не вставляет. Вначале в этом примере мы стартуем транзакцию - т.е. говорим о том, что последует серия каких-либо команд по вставке-удалению-изменению базы данных, которая должна выполниться целиком или, в случае чего-то, не выполняться (тогда база данных будет возвращена в положение до старта транзакции)
далее идет операция вставки, однако - с ошибкой.
Вставляется же примерно так:

Код: Выделить всё

 ContentValues values = new ContentValues();
  values.put("Name", queryValues.get("name"));
  database.insert("student", null, values);
1 строка - инициализируем специальную переменную, которая будет содержать ПАРЫ значений - имя поля и его значение.
2 строка - добавляем туда к примеру 1 пару
3 строка - вставка.
Таким образом в вашем примере неверный третий параметр, это не строковая величина должна быть, а типа
ContentValues

Затем нужно отловить ошибки и подтвердить или откатить транзакцию в случае ошибки либо еще чего-то.

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 30 янв 2015, 10:59
Fry
Еще хотелось бы добавить по поводу доступ в БД из разных потоков (то есть обеспечение потокобезопасности) и использование синглтона для этого. А также правильное закрытие БД в этом случае.

Получаем SQLiteDatabase через такой синглтон.

Код: Выделить всё

public class DatabaseManager {

    private int mOpenCounter;

    private static DatabaseManager instance;
    private static SQLiteOpenHelper mDatabaseHelper;
    private SQLiteDatabase mDatabase;

    public static synchronized void initializeInstance(SQLiteOpenHelper helper) {
        if (instance == null) {
            instance = new DatabaseManager();
            mDatabaseHelper = helper;
        }
    }

    public static synchronized DatabaseManager getInstance() {
        if (instance == null) {
            throw new IllegalStateException(DatabaseManager.class.getSimpleName() +
                    " is not initialized, call initializeInstance(..) method first.");
        }

        return instance;
    }

    public synchronized SQLiteDatabase openDatabase() {
        mOpenCounter++;
        if(mOpenCounter == 1) {
            // Opening new database
            mDatabase = mDatabaseHelper.getWritableDatabase();
        }
        return mDatabase;
    }

    public synchronized void closeDatabase() {
        mOpenCounter--;
        if(mOpenCounter == 0) {
            // Closing database
            mDatabase.close();

        }
    }

}
Тогда можем работать с БД так, в том числе из разных потоков. Закрывать базу напрямую не нужно, только через этот же сингтон!

Код: Выделить всё

 // In your application class
 DatabaseManager.initializeInstance(new MySQLiteOpenHelper());

//Thread1:
SQLiteDatabase database = DatabaseManager.getInstance().openDatabase();
database.insert(...);
database.update(...);
// database.close(); Don't close it directly!
DatabaseManager.getInstance().closeDatabase(); // correct way

//Thread2:
SQLiteDatabase database = DatabaseManager.getInstance().openDatabase();
database.insert(...);
database.update(...);
DatabaseManager.getInstance().closeDatabase(); 

На базе этого: http://stackoverflow.com/questions/2493 ... on-android

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 30 янв 2015, 12:11
Foenix
что ж у тебя и статик и инстанс, выбери уж что-нибудь одно и не декларируй этот код как истину, плиз :)
Код будет работать неэффективно, долго.
И вообще это очень устаревший подход и ненужный. Контент-провайдеры, еще раз повторяю - тем, кто хочет писать по-человечески.

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 30 янв 2015, 12:57
Fry
Foenix писал(а):что ж у тебя и статик и инстанс, выбери уж что-нибудь одно и не декларируй этот код как истину, плиз :)
Не очень тебя тут понял в смысле статик и инстанс. Ты о чем?

Я и не декларирую как истину, просто как одно из решений, которое попалось )

Я не против контент провайдеров, просто в этом уроке было прямое соединение с БД, поэтому и решение соответствующие.

Кстати, а Content Provider что - автоматически решает проблему с соединением с БД из разных потоков?

Там же точно также используется получение SQLiteDatabase из DBHelper...

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 30 янв 2015, 13:03
Foenix
решает
про паттерн синглтон почитай, чтоб понять про статик и инстанс.

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 30 янв 2015, 13:23
doter.ua
Fry писал(а):
Foenix писал(а):что ж у тебя и статик и инстанс, выбери уж что-нибудь одно и не декларируй этот код как истину, плиз :)
Не очень тебя тут понял в смысле статик и инстанс. Ты о чем?

Я и декларирую как истину, просто как одно из решений, которое попалось )

Я не против контент провайдеров, просто в этом уроке было прямое соединение с БД, поэтому и решение соответствующие.

Кстати, а Content Provider что - автоматически решает проблему с соединением с БД из разных потоков?

Там же точно также используется получение SQLiteDatabase из DBHelper...
Суть static понимаешь хоть?

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 30 янв 2015, 13:49
Fry
Foenix писал(а):решает
про паттерн синглтон почитай, чтоб понять про статик и инстанс.
Читал и реализовывал. В чем проблема-то?
Код рабочий, только что проверял.

Зы. По поводу того, что CP решает проблему совместного доступа ты ожидаемо права. Вот тут http://www.androiddesignpatterns.com/20 ... abase.html решение с CP описывается как полноценная замена темы с синглтоном.

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 30 янв 2015, 13:53
Foenix
ты ожидаемо права.
да ты шо)) это не я права, а гугл
Читал и реализовывал. В чем проблема-то?
Код рабочий, только что проверял.
не реализовывал, а копипастил не подумав даже.
ты взял щас на масло намазал масло, а хлеба нет.

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 30 янв 2015, 14:02
Fry
Foenix писал(а): да ты шо)) это не я права, а гугл
Гуглишь чтоли перед тем, как ответы писать? ))
не реализовывал, а копипастил не подумав даже.
ты взял щас на масло намазал масло, а хлеба нет.
Не надо тут. Я про него читал в сборнике паттернов и сам писал на разных примерах.

А конкретно этот пример таки да, скопипастил, но меня в нем не смутило ничего.

Пятый раз спрашиваю - в чем конкретно проблема?

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 30 янв 2015, 14:06
Foenix
а по-твоему гугл - это только поисковая система??

третий раз говорю - покажи ссылку, где написано писать в паттерне синглтон слово статик

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 30 янв 2015, 19:55
Fry
Foenix писал(а):а по-твоему гугл - это только поисковая система??
Остальное у него так себе :)
Foenix писал(а): третий раз говорю - покажи ссылку, где написано писать в паттерне синглтон слово статик
Да сколько хочешь.

Википедия: Синглетон на Java. Initialization on Demand Holder

На хабре: 5 примеров Синглетона, все с использованием static
http://habrahabr.ru/post/27108/

Ну и т.д.

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 30 янв 2015, 20:32
Foenix
отлично) по-моему, это того стоило - посмотреть еще раз на ссылки)

так а для чего там статик, тут тему разные люди читают, можешь объяснить?

Re: Урок 38. Транзакции в SQLite. Небольшой FAQ по SQLite.

Добавлено: 31 янв 2015, 10:59
Fry
Ну в чем смысл синглетона - у нас объект этого класса должен иметь только одну копию. Он же инстанс. И сколько бы мы не пытались сделать его копию, она всегда должна быть одна.

Как мы это делаем в данном случае? Объевляем поле класса instance, тип этого поля - наш же класс синглетон. Его мы будем возвращать при попытке сделать инстанс нашего класса, при этом возвращаемый обект будет один и тот же. Для этого мы его делаем static, то есть значение этого поля принадлежит не отдельному объекту, а всему классу. Метод, который будет возвращать значение этого поля делаем static по той же причине.

Все это, по большому счету, способ №4 по ссылке с Хабра.

initializeInstance - это мы в сингтон передаем объект SQLiteOpenHelper для работы с БД, ради которого все и затевалось. Это фактически просто сеттер поля такой, плюс для последующей проверки, что этот сеттер был сделан.

Foenix, теперь твоя очередь. Рассказывай, в чем проблема? :)