Использование интерфейса JNI в RDM EmbeddedИсточник: wwwbirdstepcom
База данных (БД) RDM Embedded компании Birdstep включает в себя Java-интерфейс, который использует JNI. Интерфейс JNI предоставляет разработчикам на языке Java доступ к тому же компактному и высокопроизводительному ядру БД, которое используется с помощью С/С++. Эта статья поясняет, как максимально быстро настроить и начать использовать интерфейс JNI. Подразумевается, что вы обладаете базовыми знаниями по разработке на Java, а также понимаете, как пользоваться С-интерфейсом RDM Embedded. НастройкаВот что необходимо для доступа к данным в RDM Embedded (RDMe) из Java-приложения. 1. Пакет Java SDK (версии 1.2 или старше), который поддерживает JNI. 2. RDM Embedded 7.x для той платформы, на которой вы разрабатываете приложения, и на которой их будут развертывать. После выполнения этих компонентов требуются три простых шага по конфигурации. 1. Среда Есть две настройки окружения, которые необходимо применить для получения доступа к данным из программы на Java. Метод их установки будет зависеть от того, как вы используете компилятор java: напрямую или через интегрированную среду разработки (IDE).
2. База данных Доступ из Java к БД RDM Embedded (RDMe) предоставляется через несколько генерируемых классов, создаваемых компилятором БД RDM Embedded, который называется ddlp. Когда при запуске ddlp указывается флаг -JNI, будет создан исходный файл Java для каждой записи, указанной в определении БД. Для простой схемы, показанной в листинге, будет создан единственный исходный файл с названием SIMPLE_REC.java. database simple_db { data file "simple.d01" contains simple_rec; record simple_rec { char first_name[32]; char last_name[32];
} }
3. Приложение Для подготовки приложения к использованию интерфейса JNI нужно просто включить следующие операторы импорта в исходные файлы на Java: import com.birdstep.rdme.jni.*; import com.birdstep.rdm.*; Теперь приложение готово для доступа к данным из RDM Embedded. Приложение "Hello World" с использованием интерфейса JNI для RDM Embedded (RDMe)Теперь мы создадим очень простое приложение "Hello World" ("Привет, мир"). Приложение будет открывать БД simple_db, добавлять новую запись simple_rec и показывать все данные, хранящиеся в simple_rec (включая вновь добавленную запись). Есть два базовых Java-класса RDMe, которые используются для взаимодействия с ядром БД. Первый- это класс RDMe Task, второй - класс RDMe Database. Эти классы подробно описаны в документации на JNI, однако это описание можно свести к следующим двум положениям:
Для этого примера я создал два класса: SimpleExample в качестве основного класса и SimpleDb в качестве класса доступа к БД. Класс SimpleDb имеет переменные-члены Task и Database, которые управляют доступом к БД simple_db. 1 шаг: создание объекта RDMe Task В конструкторе для класса SimpleDb мы создадим и инициализируем наш объект Task. Мы проделаем минимальную необходимую инициализацию объекта Task, укажем тип Lock Manager и идентификатор пользователя БД. /* Создание объекта Task */ try{ taskObj = new Task(); taskObj.lockcomm("Internal"); taskObj.dbuserid("simple_user"); } catch(DBException e) { throw e; } 2 шаг: открытие БД После создания объекта Task мы создадим объект Database путем вызова открытой функции-члена объекта Task. Для этого примера нужно, чтобы файлы БД
(simple_db.dbd и simple.d01) находились в том же каталоге, в котором мы выполняем приложение. /* Открытие БД */ try{ dbObj = taskObj.open("simple_db", "s"); } catch (DBException e) { System.out.println("Failed to open simple_db " + e.getErrorNumber()); throw e; } 3 шаг: вставка новой записи Теперь, когда мы успешно создали и инициализировали наши объекты Task и Database, мы можем их использовать для работы с нашей БД. Поскольку важно использовать хорошие методики разработки БД, мы начнем транзакцию, запросим блокировку, добавим новые данные и зафиксируем транзакцию. /* Начало транзакции, блокировка записи, добавление, фиксации */ try { taskObj.trbegin("simple_rec_insert"); dbObj.reclock(simple_db.SIMPLE_REC, "w"); dbObj.fillnew(simple_db.SIMPLE_REC, sr); taskObj.trend(); } catch (DBException e) { System.out.println("Failure inserting record " + e.getErrorNumber()); /* Прерывание транзакции в случае ошибки */ taskObj.trabort(); throw e; } 4 шаг: чтение данных Мы проверим данные, которые только что ввели. Для облегчения этой задачи мы заблокируем current_rec, используем recfrst/next для организации цикла по всем записям, считаем simple_rec и напечатаем содержимое. /* Блокировка записи и цикл по всем экземплярам*/ try { dbObj.reclock(simple_db.SIMPLE_REC, "r"); for(stat = dbObj.recfrst(simple_db.SIMPLE_REC); stat == RDME.S_OKAY; stat = dbObj.recnext() ) { /* чтение и показ записи */ dbObj.recread(sr); System.out.println(sr.getFIRST_NAME() + " " + sr.getLAST_NAME() ); } /* снятие блокировки */ dbObj.recfree(simple_db.SIMPLE_REC); }
catch (DBException e) { System.out.println("Failure reading simple_rec " + e.getErrorNumber()); /* снятие блокировки в случае ошибки */ dbObj.recfree(simple_db.SIMPLE_REC); throw e; } 5 шаг: очистка Для завершения приложения мы используем метод финализации SimpleDb, чтобы закрыть объект Database и освободить ресурсы, связанные с объектом Task. try { if(dbObj != null) { dbObj.close(); dbObj = null; } if(taskObj != null) { taskObj.closetask(); taskObj = null; } } catch(DBException e) { System.out.println("Failed to close " + e.getErrorNumber()); } 6 шаг: компиляция и выполнение Все, что осталось сделать после выполнения этих шагов - это компиляция и выполнение программы. За 6 простых шагов мы создали приложение на Java, которое может использовать данные совместно с программой на С для RDM Embedded. Взяв эту программу в качестве исходной точки, не составит труда создать приложение для доступа к вашим собственным данным. "Подводные камни" программированияВот несколько ошибок программирования, которые я совершил при подготовке этого примера, и способы их исправления. КомпиляцияПроблема simple_db.java:1: package com.birdstep.rdme.jni does not exist Решение Добавить путь к файлу rdm_embedded.jar в переменную classpath Проблема SimpleExample.java:63: cannot resolve symbol symbol : class SIMPLE_REC location: class SimpleDb SIMPLE_REC sr;
Решение
ЗапускПроблема Exception in thread "main" java.lang.UnsatisfiedLinkError: no RDMEjni in java.library.path at java.lang.ClassLoader.loadLibrary(Unknown Source) at java.lang.Runtime.loadLibrary0(Unknown Source) at java.lang.System.loadLibrary(Unknown Source) at com.birdstep.rdme.jni.Task.<clinit>(Task.java:71) at SimpleDb.<init>(SimpleExample.java:21) at SimpleExample.main(SimpleExample.java:134) Решение Убедитесь, что dll-файлы динамических библиотек RDM Embedded или совместно используемые объекты указаны в переменной окружения системных путей. Проблема Failed to open simple_db -4 DBException: com.birdstep.rdm.DBException: RDM Database Error: -4 at com.birdstep.rdme.jni.Database.validate(Database.java:716) at com.birdstep.rdme.jni.Database.open(Database.java:150) at com.birdstep.rdme.jni.Database.<init>(Database.java:143) at com.birdstep.rdme.jni.Task.open(Task.java:99) at SimpleDb.<init>(SimpleExample.java:30) at SimpleExample.main(SimpleExample.java:134) Решение Убедитесь, что вы скомпилировали (с помощью ddlp) и инициализировали (с помощью initdb) схему simple_db (simple_db.ddl). Полный исходный код Исходный код для схемы БД и код на Java можно загрузить с узла: ftp://ftp.raima.com/outgoing/DatabaseInsights/simple_jni.tgz |