
Продолжаем продолжать
Итак, в последний раз мы прошли такую себе мини-лекцию по базам. Сегодня время пришло заняться практикой.
Начнем с первого пункта:
Создание базы данных
В Андроиде я насчитал 3 способа создания базы данных. Начнем с самого неправильно, и закончим самым православным.
1 способ – использовать класс SQLiteDatabase. Для начала сделаем небольшой обзор этого класса, так как в будущем он нам ой как пригодится.
Иерархия:
java.lang.Object
android.database.sqlite.SQLiteClosable
android.database.sqlite.SQLiteDatabase
Предков всего ничего: стандартный явовский Object и интерфейс SQLiteClosable. Последний мы вряд ли мы когда-нибудь будем использовать — это всего лишь внутренний интерфейс, которой исходя из названия содержит в себе методы, необходимые для закрытие (удаления) SQLite классов. В данном случае его наследует наш SQLiteDatabase, который следовательно представляет из себя ресурс, который можно прикрыть, если что)
Перейдем к рассмотрению наиболее популярных методов. Для начала просто опишем их, не вдаваясь в подробности, как с ними работать:
- void execSQL(String sql) — выполнение sql-запроса, который не является выборкой (т.е. без select). Это всякие CREATE TABLE, INSERT, DELETE и так далее.
- Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) — большой и важный метод с кучей параметров. Используем для выборки. Параметры сами за себя говорят. Подробнее обсудим позже
- Cursor rawQuery(String sql, String[] selectionArgs) — сырой, обычный, дикий sql-запрос. Очень полезно иметь возможность обратиться к базе, используя всякие хитрые Join’ы и так далее.
Дальше я не буду сильно описывать следующие методы. Скажу лишь, что они представляют цивильный способ совершения часто встречаемых запросов:
- insert() – возвращает id вставленной строки
- update() – возвращает количество обновленных строк
- replace() – не часто встречал такой метод в других API. Нужно поковыряться еще. Замена.
- delete() – возвращает количество удаленных строк
Дальше пойдут методы, которые возвращают ответ «Да» или «Нет»:
- isOpen() – true, если база была не закрыта
- isReadOnly() – true, если база была открыта только для чтения
Методы для работы с транзакциями:
- beginTransaction() – начало
- endTransaction() – конец
- inTransaction() – true, если открыта транзакция
- setTransactionSuccessful() – только после вызова этого метода транзакция будет закомичена.
Остальные вряд ли будут часто использоваться. С вышеперечисленными пока не будем сильно заморачиваться, а остановимся над тем, с чего собственно начали — создание базы.
Как я и говорил, существует 3 способа это сделать. И одним из этим способов является метод openDatabase(). Вот его полное описание:
static SQLiteDatabase openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags)
где:
- path — путь к файлу базы данных. Путь для любой базы данных имеет вид: «/data/data/<package_name>/databases. <package_name> – имя пакета, которое вы указывали при создании проекта. Что-то вроде com.google.android.maps. Ну, или com.example.mysmallapp
- factory — хз, что такое. По умолчанию стоит null — пусть так и стоит, пока не будет трогать.
- flags — флаги или константы, определенные внутри класса SQLiteDatabase. Их всего четыре: CREATE_IF_NECESSARY (создавать базу, если это нужно), OPEN_READONLY (открыть только для чтения), OPEN_READWRITE (читать и писать), NO_LOCALIZED_COLLATORS (открыть без поддержки локализации)
Т.е. для того, чтобы создать базу с нуля нам нужно вызвать метод openDatabase() примерно таким образом:
SQLiteDatabase mDatabase = SQLiteDatabase.openDatabase("/data/data/com.example.app/databases/my.db", null, SQLiteDatabase.CREATE_IF_NECESSARY);
Все. Таким образом, мы получили новую, чистую базу данных для дальнейшей работы. Так как флаг SQLiteDatabase.CREATE_IF_NECESSARY пишут в конце очень часто при открытии, разработчики Андроида решили предложить метод openOrCreateDatabase() для краткости:
SQLiteDatabase mDatabase = SQLiteDatabase.openOrCreateDatabase("/data/data/com.example.app/databases/my.db", null);
Так даже удобнее. Но это только первый способ.
2 способ — это метод openOrCreateDatabase() в классе Context. О классе Context особо поговорим потом. Сейчас остановимся но том, что он представляет объект для общения с ОС Андроида.
Если вам доступен объект типа Context, то очень рекомендуется использовать его метод openOrCreateDatabase(). Почему? Для начала разберем его поподробнее:
SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory)
где
- name — имя базы данных, уникальное в рамках приложения
- mode — константа, для указания режима (MODE_PRIVATE или 0 – по умолчанию, MODE_WORLD_READABLE для чтения, MODE_WORLD_WRITEABLE для записи)
- factory — пока не трогаем, ставим null
Возвращает этот метод объект типа SQLiteDatabase.
Какие преимущества у такого способа? Оно одно — нам не нужно указывать полный путь к файлу базы данных. Достаточно только ее имени. Так как путь к приложению мы уже знаем исходя из данных, которые предоставляет Context.
Для полноты картины разберем еще несколько методов класса Context для работы с базами данных:
- boolean deleteDatabase(String name) — удаляем базу по имени. True, если завершилось успешно.
- File getDatabasePath(String name) — возвращает абсолютный путь по имени базы
Со вторым способом мы разобрались. Перейдем к следующему, самому православному способу, который советуют использовать разработчики Гугла.
3 способ — использовать SQLiteOpenHelper.
Как становится ясно из названия, SQLiteOpenHelper помогает нам открывать/создавать базы данных. Начнем с описания класса:
Иерархия:
java.lang.Object
android.database.sqlite.SQLiteOpenHelper
Здесь все. Также все просто и с методами. Их всего 6. 2 из них — абстрактные, и их следует переопределять в потомках. Перечислим первые 4:
- void close() – закрыть все открытые соединения
- SQLiteDatabase getReadableDatabase() – возвращает базу для чтения
- SQLiteDatabase getWritableDatabase() – база для чтения и записи
- onOpen(SQLiteDatabase db) — вызывается после того, как база будет открыта
И 2 абстрактных метода:
- onCreate(SQLiteDatabase db) — вызывается после того, как база создана в первый раз. Здесь мы создаем необходимые таблицы. И если нужно, заносим в них какие-либо начальные данные.
- onUpgrade(SQLiteDatabase db) — вызывается, когда базе нужен апгрейд. Здесь мы удаляем таблицы, создаем новые, добавляем поля и так далее.
Ну, и конструктор:
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
где
- context — контекст приложения. Именно через его метод openOrCreateDatabase() и работает SQLiteOpenHelper
- name — имя базы
- factory — говорили уже
- version — версия базы. Используется, когда схему базы данных нужно обновить.
Приведем пример наследования и использования SQLiteOpenHelper:
class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "data";
private static final String DATABASE_CREATE = "create table test_table (_id integer primary key autoincrement, some_test text not null);";
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS notes");
onCreate(db);
}
}
Здесь мы использовали паттерн Шаблон для инкапсуляции внутренних данных. Для использования базы теперь нужно лишь вызвать getReadableDatabase() или getWriteableDatabase() метод. Т.е.:
DatabaseHelper mDbHelper = new DatabaseHelper(mCtx);
SQLiteDatabase mDb = mDbHelper.getWritableDatabase();
И мы получим нашу любимую базу. Все очень просто и лаконично смотриться.
Конец второй части
На этом пока остановимся. Дальше разберем, как же все таки работать со всеми этими методами — insert(), update(), replace(), delete() и тому прочее. Постараюсь этому как-нибудь выделить время. Пока всем.
Прикольно расписано, а то полез в туториалсы от http://developer.android.com, то как-то со старта – темный лес =))
— Gremlin · дек 3, 00:03 · #
Спасибо. Сам писал в процессе изучения. К сожалению, в последнее время не удается вернуться к Андроиду из-за нехватки времени.
— iobit · дек 3, 14:46 · #