воскресенье, 31 января 2016 г.

Взаимодействие с данными в Oracle MAF(ADF Mobile). Часть 2. Работа с БД ( Work with DB in Oracle MAF)

Часть 1: http://www.oracle-adf.info/2015/05/oracle-mafadf-mobile-1-soap-xml-web.html

Обычно мобильные приложения  работают с данными при помощи сервисов. Но часто бывают случаи когда данные нужно хранить на мобильном устройстве. В этой статье я расскажу как работать с SQLite в MAF. Рабочая версия приложения c SQLite находится  на github:  https://github.com/JealousyM/sqlite-maf

SQLite компактная встраиваемая реляционная база данных и идеально подходит для хранения данных в мобильных устройствах.

Работа с SQLLite Database.


Первым шагом является  создание самой бд при помощи JDBC.  В SQLite каждая бд находится в собственном файле. Есть два способа для создания бд SQLite. Первый способ - это использование DML запросов через JDBC(таких как create table). Второй способ - это использование ранее созданного файла. Файл будет упакован с кодом вашего мобильного приложения. Он должен храниться в определенном месте, что бы ваше приложение могло загрузить его. Существует много утилит для создания и работы с такими файлами (MesaSQLite, SQLiteManager,  SQLiteDatabase Browser)



Соединение к SQL Database

Что бы соединиться в вашем мобильном приложении к  бд SQLite, вы должны использовать JDBC. Первый шаг  : необходимо найти где находится бд на устройстве. Для этого существует класс AdfmfJavaUtilities содержащий метод  getDirectoryPathRoot(). Этот метод дает доступ к файловой системе устройства(и к Android, и к iOS). Вы можете использовать этот метод что бы получить доступ к временным файлам, файлам приложения, к cache  директориям используя TemporaryDirectory, ApplicationDirectory и DeviceOnlyDirectory константы.  Так как файл бд деплоится вместе с мобильным приложением, он хранится в  ApplicationDirectory. Что бы начать работу с бд в maf приложении нужно создать класс  DBConnectionFactory в ApplicationController. Этот класс управляет соединениями с бд



Добавьте в него метод getConnection


И метод closeConnection




Ограничения SQL Lite

SQLite очень мощная бд, но имеет ряд ограничений. Первое ограничение связано с паралелизмом. Вы можете иметь множество одновременных соединений    к бд в режиме для чтения, но только одно для записи. Это является проблемой, если мобильное приложение многопоточно.
Второе ограничение,  SQLite не поддерживает full outer join и right outer join . Так же  SQLite не поддерживает права пользователей.  Так же,  когда вы создаете таблицу вы можете указать типы данных для полей. Но при работе с бд не происходит проверки типов. Это значит, что вы можете вставить строку в поле с типом Integer.
Кроме этих ограничений, есть не сколько ограничений по поддержке транзакций. SQLite
не поддерживает вложенные транзакции.  Когда вы имеете несколько открытых соединений и каждое из них выполняет commit, только первая транзакция будет выполнена успешно. Все остальные соединения будут переключены в режим read-only.

Команда  VACUUM 

Когда вы удаляете  записи с бд, ее размер не меняется. Это приводит к фрагментации после удаления записи, и приводит к снижению производительности. Вы можете избежать это, периодически выполняя команду VACUUM. Эта команда имеет опции: http://www.sqlite.org/lang_vacuum.html

Пример использования в maf: connetcion.preparedStatement('PRAGMA auto_vacuum=FULL;");


Создание объектов БД

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

Пример скрипта:



Если вы хотите использовать скрипт в мобильном приложении для создания бд, необходимо добавить этот скрипт в  ApplicationController как resource( положить в папку  META-INF).
Далее нужно создать метод который будет выполнять скрипт. Этот метод будет содержать следующие шаги:
1. Поиск ApplicationDirectory.
2. Присваивание имени бд.
3.  Проверка существует ли бд, и если существует, то не создавать её.
4.  Если бд не существует, то создать ее.
5. Использовать файл скрипта как  Stream для построчного разбора
6. Выполнить все SQL запросы.
7. Выполнить commit

Код должен выглядеть так :



Этот метод нужно добавить в метод start() в LifeCycleListenerImpl.


Работа с данными

Что бы работать с данными из бд, нужно создать сущность  таблицы в бд c  методом clone(этот метод нам нужен для работы с данными)

Потом сгенерировать  сеттеры и геттеры,  с опцией "Notify listeners when property changes"





Автоматически сгенерируется  PropertyChangeSupport объект  который в каждом сетере  будет вызывать  firePropertyChange. Так же сгенерируются методы  addPropertyChangeListener и removePropertyChangeListener.

Теперь когда будет вызываться сеттер у свойства, будет вызываться  firePropertyChange с новым и старым значением. Фрэймворк будет вылавливать изменения в данных и уведомлять пользовательский интерфейс, что данные изменились( это заменяет в MAF  технологию AJAX)


Дальше для получения и сохранения данных в бд нужно создать класс DBAdapter c со следующими методами:



После этого нужно создать класс UserAdapter, который будет  получать,изменять,удалять данные из нашей таблицы





После этого нужно создать класс для Data Control. Назовём его UserDC




Далее нужно создать сам Data Control. Для этого нажмите  правой кнопкой по ранее созданному классу, и выберите "Create Data Control"
Появится мастер создания Data Control-a. Где в первом окне вводится имя dc и выбирается класс на основе которого он создается. 


Во втором окне выбирается режим  доступа


Теперь, когда создан dc в нем отображаются методы созданные нами. И путем простого перетягивания на amx страницу можно использовать эти методы. Продемонстрируем это выводом списка пользователей. Для этого перенесите users на amx страницу и  выберите MAF List View


Далее нужно выбрать вид списка и что в нем выводить







Теперь если задеплоить приложение на телефон или в эмулятор, то приложение загрузит имена пользователей:


Готово. Если непонятно, как добавлять, удалять и изменять данные на amx странице...то пишите в комментариях : )