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

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

Добавлено: 01 дек 2011, 03:00
damager82
В этом уроке:

- используем транзакции при работе с БД

Click here to read this article!

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

Добавлено: 10 май 2012, 08:09
eugene78
Спасибо за статью, пригодилась.
Вот еще в тему http://www.enterra.ru/blog/android_issues_with_sqlite/, тоже кое-что полезного взять можно.

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

Добавлено: 10 май 2012, 09:49
damager82
eugene78 писал(а):Спасибо за статью, пригодилась.
Вот еще в тему http://www.enterra.ru/blog/android_issues_with_sqlite/, тоже кое-что полезного взять можно.
Спасибо, хороший материал! Добавлю ссылку в урок.

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

Добавлено: 18 май 2012, 22:35
icamys
Спасибо большое! Отличный урок.

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

Добавлено: 04 июн 2012, 10:44
alex6999
Это очень важно! Т.е. если вы открыли транзакцию, выполнили какие-либо действия и не закрыли транзакцию, то все операции будут считаться успешными и изменения будут внесены в БД. Поэтому закрытие транзакции необходимо выполнять и finally нам это гарантирует.
тут вроде надо
Это очень важно! Т.е. если вы открыли транзакцию, выполнили какие-либо действия и не закрыли транзакцию, то все операции будут считаться неуспешными и изменения не будут внесены в БД. Поэтому закрытие транзакции необходимо выполнять и finally нам это гарантирует.

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

Добавлено: 04 июн 2012, 11:20
damager82
alex6999 писал(а): тут вроде надо
Это очень важно! Т.е. если вы открыли транзакцию, выполнили какие-либо действия и не закрыли транзакцию, то все операции будут считаться неуспешными и изменения не будут внесены в БД. Поэтому закрытие транзакции необходимо выполнять и finally нам это гарантирует.
Да, чето я фигню написал какую-то ... Спасибо за наблюдательность! Пофиксил

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

Добавлено: 30 авг 2012, 15:46
d79
void myActions() {
db = dbh.getWritableDatabase();
delete(db, "mytable");
db.beginTransaction();
insert(db, "mytable", "val1");
db.setTransactionSuccessful();
insert(db, "mytable", "val2");
db.endTransaction();
insert(db, "mytable", "val3");
read(db, "mytable");
dbh.close();
}
Обратите внимание - несмотря на то, что val2 мы вставляли уже после подтверждения успешности транзакции, запись вставилась, вошла в эту транзакцию.
Получается, расположение метода setTransactionSuccessful() может быть любым между открытием и закрытием транзакции?

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

Добавлено: 05 сен 2012, 09:37
damager82
d79 писал(а):Получается, расположение метода setTransactionSuccessful() может быть любым между открытием и закрытием транзакции?
Получается так. Но, походу, это не приветствуется, т.к. в хелпе есть такой текст: "Do not do any more database work between calling this and calling endTransaction."

Пожалуй, надо мне отметить это в уроке.

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

Добавлено: 03 фев 2013, 17:39
SoLVeX
Так же смогу сказать что, например, вставка записей (к примеру 1к) проходит быстрее в транзакции чем без.
Кстати актуально не только для SQLite

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

Добавлено: 07 мар 2013, 08:45
Prospekt
Интересен такой момент: а что если делать SQLiteOpenHelper синглетоном?
Вроде работает нормально, и можно методы доступа синхронизировать. Вопрос только в том, надо ли закрывать SQLiteOpenHelper?
После каждого обращения делать закрытие накладно, но если никогда не закрывать (...close()), то что будет при убивании всех экземпляров активити, работающих с этим Хелпером?
Я так понимаю, что умная система должна сама убить (закрыть) Хелпер, как она закрывает например все in\outStream при выходе. Или же статический объект будет висеть вечно? Как вариант, можно запоминать время последнего обращения к хелперу, и если оно больше скажем 5 минут, то хелпер уничтожается. И при запросе воссаздается заново.

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

Добавлено: 07 мар 2013, 08:54
neoksi
Prospekt писал(а):Интересен такой момент: а что если делать SQLiteOpenHelper синглетоном?
Вроде работает нормально, и можно методы доступа синхронизировать. Вопрос только в том, надо ли закрывать SQLiteOpenHelper?
После каждого обращения делать закрытие накладно, но если никогда не закрывать (...close()), то что будет при убивании всех экземпляров активити, работающих с этим Хелпером?
Я так понимаю, что умная система должна сама убить (закрыть) Хелпер, как она закрывает например все in\outStream при выходе. Или же статический объект будет висеть вечно? Как вариант, можно запоминать время последнего обращения к хелперу, и если оно больше скажем 5 минут, то хелпер уничтожается. И при запросе воссаздается заново.
Это будет велосипедом, для этого есть СontentProvider, который является синглтоном и все это берет на себя.

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

Добавлено: 07 мар 2013, 09:21
Prospekt
Гы,
У многих есть неравнодущее к некоторым аспектам программирования, некоторые видят все мировое зло в несоблюдении правил отступа, некоторые считают мастерское владение дебагером сутью программирования, а товарищ neoksi помещан на КонтентПровайдерах. Прямо через пост.

За ответ спасибо, но как-то это не то.
КП определенно хороши, но хочется вариант поминиатюрней. Хотя определенно большая часть правда в вашем посте содержится. Как я понимаю, Вы предлагаете все обращения к БД делать исключительно через КП?
И всеже если взяться за ответку и прикрутить 2 колеса. Ну хотя бы как вариант.

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

Добавлено: 07 мар 2013, 09:27
neoksi
damager82 писал(а):
d79 писал(а):Получается, расположение метода setTransactionSuccessful() может быть любым между открытием и закрытием транзакции?
Получается так. Но, походу, это не приветствуется, т.к. в хелпе есть такой текст: "Do not do any more database work between calling this and calling endTransaction."

Пожалуй, надо мне отметить это в уроке.
Тут нужно учесть, что SQLite однопоточная БД и очередность запросов отдана на откуп программистам пишущим приложения.

1) Метод beginTransaction() отправляет в движок SQL команду скапливать запросы и не обрабатывать их;
2) Метод setTransactionSuccessful() отправляет в движок SQL команду, что блок запросов завершен;
3) Метод endTransaction() отправляет в движок SQL команду, распарсить и обработать запросы, которые были указанны в блоке транзаксации.

Если между 2 и 3 методом отправить ещё н-ное кол-во запросов, то они будут немедленно обработаны и запишутся в файл БД до обработки блока транзаксации. Но может возникнуть ситуация, когда этими запросами будет блокирован на запись файл БД, к которому затребует доступ блок транзаксации, что в свою очередь приведет к возникновению исключения доступа к файлу.

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

Добавлено: 07 мар 2013, 09:38
Prospekt
Я понимаю это, но ведь такие ограничения остаются и для ContentProvider-ов. Большинство примеров БД - это маленькие базы с одной таблицей, с мелкими методами getItem() getAll() insertItem() updateItem() deleteItem() и эти методы можно сделать синхронизированными виду малости исполняемого кода. (Не повлияет на скорость).
Согласитесь, что во множестве случаев легче иметь простенький вариант решения, а городить 3-4 таблицы, связанных между собой - это редкость. Пока встречал варианты только простых БД.

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

Добавлено: 07 мар 2013, 09:40
neoksi
Prospekt писал(а):Гы,
У многих есть неравнодущее к некоторым аспектам программирования, некоторые видят все мировое зло в несоблюдении правил отступа, некоторые считают мастерское владение дебагером сутью программирования, а товарищ neoksi помещан на КонтентПровайдерах. Прямо через пост.

За ответ спасибо, но как-то это не то.
КП определенно хороши, но хочется вариант поминиатюрней. Хотя определенно большая часть правда в вашем посте содержится. Как я понимаю, Вы предлагаете все обращения к БД делать исключительно через КП?
И всеже если взяться за ответку и прикрутить 2 колеса. Ну хотя бы как вариант.
Prospekt
Программируя на другом языке и работая с SQLite, я уже сталкивался с проблемой разграничения доступа к однопоточной БД из разных потоков программы, и честно, это была ещё та головомойка. Тут же, разработчики Андроида предусмотрели механизм, который все делает за нас, да, для понимания начального он сложен. Плюс КП дает свои плюшки, к примеру автоматическое обновление данных в отображаемых элементах при изменении их в БД. Я призываю его использовать, так как в конечном итоге он упрощает жизнь и не надо будет искать, где же и почему вдруг возникло исключение, когда два потока приложения одновременно решили поработать с БД.

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

Добавлено: 07 мар 2013, 10:01
Prospekt
По всей видимости есть необходимость в уроке "ContentProvider vs других вариантов" при работе с БД.
Какие плюсы он дает? Да комбинация ContentProvider и BroadCastResiever позволяют автоматически обнавлять данные в приложении и даже в GUI.
Согласитесь, что во множестве случаев легче иметь простенький вариант решения, а городить 3-4 таблицы, связанных между собой - это редкость. Пока встречал варианты только простых БД.
Возможно в сложных случаях это действительно головомойка, но в большинстве случаев БД в Android - это всего лишь прокладка между программой и жестким диском (или какой он там). Прогеров ломает самим считывать данные с диска и сохранять их там, поэтому используются минимум из функционала БД. Сложности возникают при полноценном юзаньи БД, как например программы на серверном оборудовании, а тут -то где можно черту ногу поломать в 3-х соснах. Я вроде не глупый, но представить ситуацию такую не могу для Android-а. Поделитесь плиз, для моего собственного развития.

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

Добавлено: 07 мар 2013, 10:23
neoksi
Prospekt
Если вы работаете с данными только из одной точки, к примеру из одной активити, то да, тут можно напрямую без КП обойтись. Но как только вы начинаете работать с данными из разных точек, активити, сервисы и ресиверы, то становится необходимым создание КП для централизации процесса и избегания проблем.

Возьмем абстрактный пример:
Есть программа будильник, которая хранит назначенные будильники в БД (это одна таблица) и ими можно управлять из активити. Но у нас программа с супер мега функцией, если послать на телефон смс в определенном формате, то она может активировать или дезактировать будильник на определенный день (реализуется через БроадкастРесивер).
И так наступает час Х, когда наш пользователь открыл активити и работает с настройкой будильника на субботу, а в тот же момент ему приходит супер смс от жены с требованием отключить будильник на субботу. Без КП, я даже не хочу гадать, какая ошибка может выскочить, при одновременном сохранении данных Пользователем и Ресивером, но с КП проблем не возникнет.

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

Добавлено: 07 мар 2013, 10:37
Prospekt
а разве synchronized не решит эту проблему, ну если синхронизировать запросы к данным?
Хотя конечно да, все равно придется БроадкастРесивер ставить, чтобы не было рассогласования между данными программы и бд.

Ладно, уговорили, может и стоит все запросы через КП делать. особых минусов, кроме объема кода нет + права на доступ выставлять.

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

Добавлено: 11 мар 2013, 18:19
insider
Вопрос не очень важный, просто по методике. Зачем в методе read проверять курсор на null? Разве может возникнуть такая ситуация? db.query все равно вернет Cursor, даже с нулем записей. А проверку мы и так сделаем в c.moveToFirst.

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

Добавлено: 15 апр 2013, 14:29
mmvds
neoksi писал(а): 1) Метод beginTransaction() отправляет в движок SQL команду скапливать запросы и не обрабатывать их;
2) Метод setTransactionSuccessful() отправляет в движок SQL команду, что блок запросов завершен;
3) Метод endTransaction() отправляет в движок SQL команду, распарсить и обработать запросы, которые были указанны в блоке транзаксации.

Если между 2 и 3 методом отправить ещё н-ное кол-во запросов, то они будут немедленно обработаны и запишутся в файл БД до обработки блока транзаксации. Но может возникнуть ситуация, когда этими запросами будет блокирован на запись файл БД, к которому затребует доступ блок транзаксации, что в свою очередь приведет к возникновению исключения доступа к файлу.
Что-то не сходится, если они действительно будут немедленно обработаны и запишутся в файл БД до обработки блока транзаксации, то почему в примере

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

void myActions() {
    db = dbh.getWritableDatabase();
    delete(db, "mytable");
    db.beginTransaction();
    insert(db, "mytable", "val1");
    db.setTransactionSuccessful();
    insert(db, "mytable", "val2");
    db.endTransaction();
    insert(db, "mytable", "val3");
    read(db, "mytable");
    dbh.close();
  }
Вывод был таким:

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

val1
val2
val3
а не таким?

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

val2
val1
val3