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

Обсуждение уроков
Аватара пользователя
vgavt
Сообщения: 8
Зарегистрирован: 12 апр 2012, 15:45

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

Сообщение vgavt » 27 сен 2013, 11:01

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

Digetix
Сообщения: 117
Зарегистрирован: 12 окт 2012, 15:31

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

Сообщение Digetix » 02 дек 2013, 14:30

Как такое получение данных правильно оформить в транзакцию?

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

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();
                                }                
                         } 
                      }
                     }); 

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

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

Сообщение Foenix » 02 дек 2013, 16:42

не получение, а вставку
Просто до цикла for стартани ее, а после цикла - завершай.
А вообще я просто объект передаю методу хэлпера и там стартую транзакцию и разбираю объект на части-вставки.
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Digetix
Сообщения: 117
Зарегистрирован: 12 окт 2012, 15:31

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

Сообщение Digetix » 02 дек 2013, 17:40

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, как правильно?

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

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

Сообщение Foenix » 02 дек 2013, 17:48

неправильно. Финишировать нужно в finaly и ЗА циклом, когда уже все записи вставлены.

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

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


        }
}
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Digetix
Сообщения: 117
Зарегистрирован: 12 окт 2012, 15:31

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

Сообщение Digetix » 02 дек 2013, 23:21

Спасибо, всё работает

TittTitov
Сообщения: 27
Зарегистрирован: 20 ноя 2013, 22:46

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

Сообщение TittTitov » 16 янв 2014, 23:36

Здравствуйте!

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

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

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

Сообщение Foenix » 16 янв 2014, 23:59

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

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

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

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

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
Fry
Сообщения: 183
Зарегистрирован: 07 дек 2013, 22:07

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

Сообщение Fry » 30 янв 2015, 10:59

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

Получаем 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
Arbeit macht Fry

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

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

Сообщение Foenix » 30 янв 2015, 12:11

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

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
Fry
Сообщения: 183
Зарегистрирован: 07 дек 2013, 22:07

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

Сообщение Fry » 30 янв 2015, 12:57

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

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

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

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

Там же точно также используется получение SQLiteDatabase из DBHelper...
Последний раз редактировалось Fry 30 янв 2015, 13:51, всего редактировалось 1 раз.
Arbeit macht Fry

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

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

Сообщение Foenix » 30 янв 2015, 13:03

решает
про паттерн синглтон почитай, чтоб понять про статик и инстанс.
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

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

Сообщение doter.ua » 30 янв 2015, 13:23

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

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

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

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

Там же точно также используется получение SQLiteDatabase из DBHelper...
Суть static понимаешь хоть?
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Аватара пользователя
Fry
Сообщения: 183
Зарегистрирован: 07 дек 2013, 22:07

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

Сообщение Fry » 30 янв 2015, 13:49

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

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

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

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

Сообщение Foenix » 30 янв 2015, 13:53

ты ожидаемо права.
да ты шо)) это не я права, а гугл
Читал и реализовывал. В чем проблема-то?
Код рабочий, только что проверял.
не реализовывал, а копипастил не подумав даже.
ты взял щас на масло намазал масло, а хлеба нет.
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
Fry
Сообщения: 183
Зарегистрирован: 07 дек 2013, 22:07

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

Сообщение Fry » 30 янв 2015, 14:02

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

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

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

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

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

Сообщение Foenix » 30 янв 2015, 14:06

а по-твоему гугл - это только поисковая система??

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

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
Fry
Сообщения: 183
Зарегистрирован: 07 дек 2013, 22:07

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

Сообщение Fry » 30 янв 2015, 19:55

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

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

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

Ну и т.д.
Arbeit macht Fry

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

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

Сообщение Foenix » 30 янв 2015, 20:32

отлично) по-моему, это того стоило - посмотреть еще раз на ссылки)

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

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
Fry
Сообщения: 183
Зарегистрирован: 07 дек 2013, 22:07

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

Сообщение Fry » 31 янв 2015, 10:59

Ну в чем смысл синглетона - у нас объект этого класса должен иметь только одну копию. Он же инстанс. И сколько бы мы не пытались сделать его копию, она всегда должна быть одна.

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

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

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

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

Ответить