2. SQLite
встраиваемая реляционная база данных
открытый исходный код.
нет отдельного сервера
высокая скорость
небольшой расход памяти
поддержка стандартных возможностей реляционных БД – синтаксис SQL, транзакции и
prepared statements
вся база данных в одном файле
кроссплатформенная
http://sqlite.org
3. SQLite в Android
доступно на любом устройстве Android
не требует установки БД или администрирования
вся работа с базой данных должна быть в отдельном потоке
файл БД хранится в каталоге приложения
5. Contract class
Хранит константы, определяющие имена для ваших URI, таблиц, колонок.
Best practice:
создаем класс, который будет хранить константы для всей базы данных
создаем внутренние классы с константами для каждой таблицы
реализуем интерфейс BaseColumns
6. SQLiteOpenHelper
Абстрактный класс, с помощью которого можно создавать, открывать и обновлять базу
данных
Создаем наследника и переопределяем следующие методы:
onCreate() - вызывается при первом создании базы данных
onUpgrade() - вызывается при модификации базы данных
Должен быть singleton
Поле id в таблице должно именоваться _id (На самом деле, нет)
close() - закрыть базу.
getReadableDatabase()/getWritableDatabase() - создают и/или открывают БД. Возвращают
объект SQLiteDatabase
7. SQLiteDatabase
Работает с базой данных SQLite напрямую, содержит методы:
insert()
update()- Используют ContentValues
delete()
query() - делает запрос к таблице и возвращает Cursor
rawQuery() - исполняет sql запрос и возвращает Cursor
execSQL() - выполнение одного sql запроса. (NOT a SELECT/INSERT/UPDATE/DELETE)
8. Cursor
Возвращается на запрос к базе данных, и предоставляет доступ к результатам запроса.
Содержит методы:
moveToFirst()
moveToNext()
типизированные методы getInt(); getLong();getString(); etc
getColumnIndex()
close()
11. Content Provider
Класс для обмена данными между приложениями.
1 <provider
2 android:authorities="com.noveo.internship.db.exampleContentProvider"
3 android:name=".database.ExampleContentProvider"
4 android:multiprocess="true"
5 android:exported="false" />
13. Content Provider
При работе с провайдером используются URI.
1 content://<authority>/<path>/<id>
authority - уникальное имя ContentProvider-а
path - какие данные нужны (имя таблицы)
id - идентификатор записи.
content://com.noveo.db.provider/toys/5
content://com.noveo.db.provider/toys
14. UriMatcher
служит для определения деталей запроса к контент- провайдеру
отображает URI разных видов на целочисленные константы
полезен в случаях, когда обслуживаются разные URI для доступа к одному и тому же
источнику данных
Пример:
Если URI оканчивается на /toys - это запрос про все игрушки
Если на toys/[ID] - про конкретную игрушку
15. Жизнь одного запроса
1. вызываем getContentResolver().query(Uri, String, String, String, String)
2. СontentResolver анализирует Uri и извлекает от туда authority
3. ContentResolver направляет запрос к ContentProvider-у зарегестрированному по этому
authority (уникальному)
4. ContentProvider выполняет запрос и возвращает Cursor (или исключение)
16. Sql to No-Sql
Когда нет желания создавать под каждую сущность отдельную таблицу.
Делаем универсальную таблицу с:
id
object_name
object_version
object_data
Сравниваем object_version класса object_name с object_version в БД.
Достаем object_data и парсимкастуем к object_name типу.
18. ORMLite
открытый исходный код
поддержка SQLite
простые аннотации, быстрый старт
при этом все гибко настраивается, нужно только залезть в документацию
http://ormlite.com/
http://habrahabr.ru/post/143431/
19. ORMLite. Модели
1 @DatabaseTable(tableName = "accounts")
2 public class Account {
3
4 public static final String NAME_FIELD_NAME = "name";
5 public static final String PASSWORD_FIELD_NAME = "passwd";
6
7 @DatabaseField(generatedId = true)
8 private int id;
9 @DatabaseField(columnName = NAME_FIELD_NAME, canBeNull = false)
10 private String name;
11 @DatabaseField(columnName = PASSWORD_FIELD_NAME)
12 private String password;
13 @ForeignCollectionField
14 private ForeignCollection<Order> orders;
15
16 Account() {
17 // Пустой конструктор обязательно должен быть(если есть непустые)
18 }
19 // Другие конструкторы
20 // Геттеры, сеттеры и проч.
21 }
20. ORMLite. DAO (Data Access Object)
Для каждого класса модели создается DAO (Класс наследник от BaseDaoImpl)
1 public class AccountDAO extends BaseDaoImpl<Account, Integer>{
2
3 protected AccountDAO(ConnectionSource connectionSource,
4 Class<Account> dataClass) throws SQLException{
5 super(connectionSource, dataClass);
6 }
7
8 public List<Account> getAllAccounts() throws SQLException{
9 return this.queryForAll();
10 }
11 }
21. ORMLite. DatabaseHelper
Наследуется от OrmLiteSqliteOpenHelper
Реализует методы: onCreate(), onUpgrade()
Создает DAO для классов, содержит методы для получения этих DAO
Должен быть синглтоном
22. ORMLite. Работа с данными
1 AccountDAO accountDao = DatabaseHelper.getHelper().getAccountDao();
2 List<Account> accounts = accountDao.getAllAccounts();
3 for (Account account : accounts) {
4 account.setPassword("new_password");
5 accountDao.update(account);
6 }
23. Realm
Использует собственное хранилище объектов, а не SQLite
Разрабатывалась специально под мобильные платформы
Не работает на Java вне Android'а
В операциях чтения показывает производительность выше, чем raw SQLite (в операциях
записи ниже)
24. Realm. Модели
Модели должны наследоваться от RealmObject
1 public class Person extends RealmObject {
2
3 // По-умолчанию все поля сохраняются в хранилище
4 private String name;
5 private int age;
6
7 // ... Геттеры-сеттеры и т.д.
8 }
25. Realm. Транзакции
1 RealmConfiguration realmCfg = new RealmConfiguration.Builder(context).build();
2 Realm realm = Realm.getInstance(realmCfg);
3
4 final Person person = realm.where(Person.class).findFirst();
5
6 realm.executeTransaction(new Realm.Transaction() {
7 @Override
8 public void execute(Realm realm) {
9 person.setName("Senior Person");
10 person.setAge(99);
11 }
12 });
26. Realm. Асинхронное выполнение операций
1 RealAsyncTask transaction = realm.executeTransactionAsync(new Realm.Transaction() {
2 @Override
3 public void execute(Realm bgRealm) {
4 //do something
5 }
6 }, new Realm.Transaction.OnSuccess() {
7 @Override
8 public void onSuccess() {
9 // Transaction was a success.
10 }
11 }, new Realm.Transaction.OnError() {
12 @Override
13 public void onError(Throwable error) {
14 // Transaction failed and was automatically canceled.
15 }
16 });
27. Realm. Асинхронное выполнение операций
Асинхронные транзакции нужно отменять, если они больше не нужны.
1 public void onStop () {
2 if (transaction != null && !transaction.isCancelled()) {
3 transaction.cancel();
4 }
5 }
28. Realm. Ограничения и недостатки
Вложенные транзакции не поддерживаются
Имя модели должно быть не больше 57 символов, имя поля - 63 символов
String и byte[] должны быть не больше 16Мб
RealmObject’ы не могут быть ключом в HashMap и храниться в HashSet
Есть некоторые проблемы с сортировкой и поиском по non-Latin строкам
29. Debug
1. Через adb shell.
cd /data/data/
cd com.noveo.internship.db
cd databases
находим файл нашей БД, test.db, например, и цепляемся туда.
sqlite3 test.db
Нужен рут. Что делать без рута?
30. Debug
Сторонние решения. Например Stetho от FB.
Позволяет многие вещи, в том числе и инспекцию БД.
SQLite databases can be visualized and interactively explored with full read/write
capabilities.
Stetho