Проведено сравнение трех наиболее популярных на текущий момент ORM-библиотек для мобильных приложений под управлением ОС Android с точки зрения производительности на примере вставки и извлечения простых POJO-объектов. Обоснован выбор определенной ORM для проектирования социального мобильного приложения.
На сегодняшний день для большинства выпускаемых программных продуктов для хранения данных используются реляционные системы управления базами данных. Использование реляционной базы данных для хранения объектно-ориентированных данных приводит к так называемому «семантическому разрыву» [1]. Это обозначает, что разработчик вынужден писатьПО, которое должно уметь одновременно обрабатывать данные в объектно-ориентированном виде (используя основной язык проектирования) и сохранять эти данные в реляционной форме (с применением SQL запросов).
Для преодоления данной проблемы применяются ORM (англ. Object-RelationalMapping) — технология программирования, которая связывает базы данных с объектами объектно-ориентированных языков программирования, создавая «виртуальную объектную базу данных».
Системы управления реляционными базами данных (СУБД) показывают хорошую производительность на глобальных запросах, которые захватывают одновременно большой объем данных. Объектно-ориентированный доступ более эффективен при работе с простыми запросами, затрагивающими малые объемы данных, так как это позволяет сократить семантический разрыв между объектной и реляционной формами данных.
Некоторые реализации ORM автоматически синхронизируют загруженные в память объекты с базой данных. Для того чтобы это было возможным, после создания объект-в-SQL-преобразующего SQL-запроса (класса, реализующего связь с DB) полученные данные копируются в поля объекта, как во всех других реализациях ORM. После этого объект должен следить за изменениями этих значений и записывать их в базу данных.
В данной работе проведено исследование производительности ORM-библиотек, на основании которого выбрана библиотека для работы с базой данных SQLite на устройствах с ОС Android.
Стоит отметить, что Android SDK предоставляет нативные средства для хранения данных [2], среди которых:
- Shared Preferences. Хранилище типа ключ-значение для примитивных типов данных, которое представляет собой обертку над XML файлом, хранящимся на устройстве. Поэтому для хранения множества однотипных структурированных данных не подходит, так как в таком случае будет занимать неоправданно большой объем памяти.
- Стандартная база данных SQLite, предоставленная с классами-помощниками в комплекте: SQLiteOpenHelper, ContentValues и др. Однако, использование этих помощников подразумевает написание шаблонного кода, отслеживание за созданием и изменением таблиц, созданием методов для операций над данными. Это накладывает трудности при дальнейшей поддержке, при добавлении новых и редактировании старых сущностей.
- Класс Content Provider. Не избавляет от необходимости реализовать логику создания, обновления таблиц и базовых CRUD операций. Положительной стороной Content Provider является возможность использовать некоторые классы платформы для асинхронности доступа и безопасности работы с данными: AsyncQueryHandler, CursorLoader, SyncAdapter и др.
Многие разработчики Android приложений используют сторонние ORM-библиотеки, которые позволяют обеспечить работу с данными в терминах классов, а не таблиц данных и напротив, преобразовать термины и данные классов в данные, пригодные для хранения в СУБД [3]. Иными словами, это позволяет не писать SQL-код для взаимодействия с данными в базе.
В работе рассмотрены 3 наиболее популярные на настоящий момент библиотеки: ActiveAndroid, ORMLite, GreenDao.
Проводимый тест проверяет, за какое время каждая библиотека может сохранять сущности в ходе SQLite транзакции, и за какое время совершит операцию по извлечению записи и сериализации в сущность. В базу данных добавляются тысяча записей, которые после перезагрузки и очищения кэша считываются и записываются в объекты. Каждая ORM проверялась пять раз, за результат взято осредненное время выполнения.
Тестовая сущность состоит из пяти полей: одно целочисленное, четыре текстовых (рис. 1). Содержание данной тестовой сущности отражает упрощенные сущности, на которых будет построена рабочая база данных, поэтому результаты проводимого теста качественно покажут, какая ORM наиболее производительная для поставленной задачи.
Рис. 1. Сущность для проведения испытаний ORM-библиотек
Результаты тестирования отражены на рис. 2 и рис. 3 в виде диаграмм.
Таким образом, наиболее производительной оказалась ORM GreenDAO.
Рис. 2. Результаты тестирования по вставке 1000 записей в таблицу
Рис. 3. Результаты тестирования по извлечению 1000 записей в таблицу
Рассмотрим создание базы данных с помощью GreenDAO в сравнении с ближайшим по скорости конкурентом ORMLite.
ORMLite использует аннотации при объявлении сущностей, что позволяет гибко вносить изменения в существующую базу данных при последующих сборках. Пример формирования рассмотренной сущности представлен в Листинге 1.
Листинг 1
Создание таблицы БД на основе сущности спомощью ORMLite
@DatabaseTable(tableName = "user")
public class AlarmEntity implements BenchmarkEntity {
@DatabaseField(columnName = "id", generatedId = true)
private long id;
@DatabaseField(columnName = "usermane")
private String usermane;
@DatabaseField(columnName = "firstname")
private String firstname;
@DatabaseField(columnName = "lastname")
private String lastname;
@DatabaseField(columnName = "vkid")
private String vkid;
}
Для формирования базы данных в GreenDAO сначала необходимо в отдельном проекте создать класс-генератор и запустить компиляцию. Пример класса-генератора приведен в Листинге 2.
Листинг 2
Класс-генератор для создания БД спомощью GreenDAO
public class DAOGenerator {
public static void main(String[] args) throws Exception {
Schema schema = new Schema(1, "com.joggle.greendao");
schema.enableKeepSectionsByDefault();
Entity entity = schema.addEntity("user");
entity.addIdProperty().autoincrement();
entity.addStringProperty("username");
entity.addStringProperty("firstname");
entity.addStringProperty("lastname");
entity.addStringProperty("vkid");
new DaoGenerator().generateAll(schema, "../src-gen/");
}
}
После этого GreenDAO сгенерирует классы, которые необходимо будет добавить в проект Android-приложения. Примерсгенерированногоклассапредставленв Листинге 3.
Листинг 3
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. Enable "keep" sections if you want to edit.
/**
* Entity mapped to table "USER".
*/
public class User {
private Long id;
private String username;
private String firstname;
private String lastname;
private String vkid;
}
В отличие от конкурентов, GreenDAO использует так называемую кодогенерацию, то есть создавать и компилировать базу данных придется в отдельном проекте. Это вынуждает совершать дополнительные действия по редактированию базы данных, по сравнению с конкурентами. Однако для мобильного приложения, в котором процессы привязаны к моменту реального времени, скорость извлечения данных является первостепенным критерием выбора ORM.
ORM — это полезный инструмент, который помогает сохранить время при разработке программных продуктов.
Данное исследование проводилось при поддержке Фонда содействия инновациям по программе «УМНИК» по договору № 9462ГУ/2015 от 03.11.2015 по теме «Разработка социального будильника для удовлетворения психологических потребностей молодежи Joggle».
Литература:
1. Rick F. van der Lans. The SQL Guide to SQLite — Paperback, 2009. – 548 pages.
2. Харди Б., Филлипс Б., Стюарт К., Марсикано К. Android. Программирование для профессионалов. 2-еизд. – СПб.: Питер,2016. — 640 с.
3. Christian Bauer, Gavin King, Hibernate in Action (In Action series) — Manning Publications, 2004. — 408 pages.