1. Вступ
PDF цього документа доступний |TYT|.
Приклади з цього документа доступні за посиланням |TYT|.
1.1. Contenu
У цьому документі ми пропонуємо розглянути різні конфігурації експлуатації бази даних. Розглянемо таку багаторівневу архітектуру:
![]() |
Потік виконання йде зліва направо:
- спочатку виконується один із класів шару [ui] (Use Interface). Він створює екземпляри шарів [metier] та [dao]. Якщо рівень [ui] є графічним інтерфейсом, він потім очікує на дії користувача. Дія користувача може спричинити виконання методів у всіх рівнях архітектури аж до бази даних. Результат цих виконань відображається користувачеві в тій чи іншій формі;
Роль різних шарів може бути такою:
- шар [JDBC] (Java DataBase Connectivity) є універсальним інтерфейсом доступу до баз даних. Він завжди надає однаковий інтерфейс шару [DAO]. Якщо змінюється SGBD, достатньо змінити драйвер JDBC. Рівень [DAO] не змінюється, якщо дотримано певних правил. Однак важко забезпечити 100% переносимість між версіями SGBD, оскільки вони часто містять значну частку пропрієтарного коду SQL, який важко ігнорувати, оскільки він часто забезпечує підвищення продуктивності. Як тільки використовується власницький SQL, перенесення між SGBD стає неможливим. Крім того, SGBD часто мають різні політики автоматичного генерування первинних ключів, а також зарезервовані слова, які в різних випадках відрізняються. У цьому документі нам все ж вдалося перенести досліджену архітектуру JDBC на шість різних SGBD, прийнявши, що для кожного з них існує окремий проект конфігурації;
- рівень [DAO] надає інтерфейс доступу до даних конкретної використовуваної бази даних (на відміну від інтерфейсу JDBC, який надає методи, що діють для будь-якого SGBD);
- шар [métier] реалізує правила управління або бізнес-правила додатка.
- її вхідними даними є дані, що надходять із бази даних через рівень [dao], та/або дані від користувача, які їй передає рівень [ui];
- вона генерує дані, які може зберегти в базі даних через шар [dao] та/або повернути шару [ui], який її запитав, для відображення користувачеві;
- шар [ui] — це шар, який виконує дії користувача та повертає йому їхні результати;
У наведеному вище прикладі шар [DAO] надсилає запити SQL до шару [JDBC] для виконання в шарі SGBD. З 2006 року ця архітектура може розвиватися таким чином:
![]() |
Відтепер саме рівень JPA (Java Persistence API) надсилає запити SQL до рівня JDBC та отримує від нього результати. Рівень [JPA] надає рівню [DAO] операції для збереження, зміни, видалення та отримання об’єктів. Рівень [DAO] більше не надсилає команд SQL. Цей підхід є більш переносимим, оскільки реалізації JPA обробляють відмінності між SGBD, але він є повільнішим, ніж технологія JDBC. Ми проведемо тести продуктивності, щоб це продемонструвати. Технологія JPA формалізує роботу, виконану фреймворком Hibernate [http://hibernate.org/] кілька років тому.
Ми розглянемо два рівні [DAO] з однією з двох наступних архітектур:
![]() |
![]() |
Ми вимагатимемо, щоб рівні [DAO1] та [DAO2] реалізовували один і той самий інтерфейс [IDAO]. Отже, тест [JUnitTestsDao] буде однаковим для обох конфігурацій і дозволить нам порівняти продуктивність. Рівень [DAO1] буде реалізовано за допомогою Spring JDBC, а рівень [DAO2] — за допомогою Spring JPA;
Після цього ми оприлюднимо інтерфейс [IDAO] у мережі Інтернет таким чином:
![]() |
- у [1] шар [IDAO] оприлюднюється у веб-середовищі через веб-шар [2], реалізований за допомогою Spring MVC. Саме інтерфейс [IDAO] надається, і ми створимо дві версії веб-сервісу залежно від того, чи реалізовано цей інтерфейс за архітектурою [DAO-JDBC] чи [DAO-JPA-JDBC];
- У [B] віддалений клієнт використовує URL, які надаються веб-сервісом і забезпечують доступ до методів шару [IDAO-serveur]. Ми забезпечимо, щоб рівень [DAO-Client] [3] реалізовував інтерфейс [IDAO-serveur] [1]. Це дозволить нам використовувати той самий тест [JUnitTestsDao], який вже двічі використовувався для [4];
- у [3] рівень [DAO-client] буде реалізовано за допомогою Spring RestTemplate;
Після цього ми забезпечимо безпеку доступу до веб-сервісу:
![]() |
- у [5] запит HTTP від клієнта проходить через рівень автентифікації, реалізований за допомогою Spring Security;
Після цього ми перетворимо попередню архітектуру на таку:
![]() |
- у [3] клієнтський додаток сам по собі є веб-додатком. Він відображатиме форму [5], що дозволяє надсилати запити URL до захищеного веб-сервісу. Доступ HTTP до захищеного веб-сервісу здійснюватиметься за допомогою шару [DAO-client-js], реалізованого на JavaScript. Ця архітектура використовує так звані міждоменні запити:
- веб-сервіс [2] надсилає запити URL у формі [http://machine1:port1/];
- веб-додаток-клієнт [3] завантажується з URL через [http://machine2:port2/]. Якщо [http://machine2:port2/] не збігається з [http://machine1:port1/] (та сама машина, той самий порт), то клієнтський браузер заблокує виклики HTTP з рівня [DAO-client-js]. Щоб вирішити цю проблему, веб-сервіс повинен дозволити міждоменні запити. Ми розглянемо, як це зробити;
Представлені проекти були протестовані з наступними шістьма версіями SGBD:
- MySQL 5 Community Edition;
- SQL Server 2014 Express;
- PostgreSQL 9.4;
- Oracle Express 11g, версія 2;
- IBM DB2 Express-C 10.5;
- Firebird 2.5.4;
Для кожного з цих SGBD було розроблено чотири різні рівні [DAO]:
- шар, реалізований за допомогою Spring JDBC;
- шар, реалізований за допомогою Spring JPA та провайдера JPA Hibernate;
- шар, реалізований за допомогою Spring JPA та постачальника JPA EclipseLink;
- шар, реалізований за допомогою Spring JPA та постачальника JPA OpenJPA;
Отже, тут представлено набір із двадцяти чотирьох різних конфігурацій. Ми доклали значних зусиль для факторизації:
- основна частина коду написана лише один раз. Вона базується на двох конфігураційних проектах Maven:
- один налаштовує рівень JDBC;
- інший — рівень JPA;
![]() |
![]() |
Проект конфігурації Maven для шару JDBC [1] певного SGBD складається з двох пунктів:
- імпортувати архів драйвера JDBC;
- визначення ідентифікаторів доступу до використовуваної бази даних та різних команд SQL, які рівень [DAO1] буде надсилати драйверу JDBC. Хоча SQL є стандартизованим, виникли проблеми з переносимістю, головним чином через наявність у запитах імен таблиць/столбців, які виявилися забороненими ключовими словами в деяких SGBD (таблиця ROLES для DB2, стовпець PASSWORD для Firebird). Крім того, хоча зазвичай імена стовпців не чутливі до регістру (великі/малі літери), у PostgreSQL виникла проблема зі стовпцем ID, що є первинним ключем таблиць. Він хотів, щоб вона називалася id з малими літерами. Ось типові приклади несподіваних проблем з переносимістю;
Три проекти Maven для налаштування шару JPA [2] певного SGBD також складаються з двох етапів:
- імпортувати архів реалізації JPA;
- налаштування реалізації JPA, що використовується для конкретного підключеного SGBD. Дійсно, саме рівень JPA надсилає команди SQL до рівня JDBC. Щоб працювати ефективно, вона повинна знати SGBD, щоб надсилати йому команди SQL, які він розпізнає. Ці команди зможуть використовувати SQL, якому належить цей SGBD, а також його особливі характеристики (типи даних, послідовності, тригери, процедури, автоматичне генерування первинних ключів тощо);
Таким чином, маємо двадцять чотири проекти (4 конфігурації × 6 SGBD) конфігурації Maven, на яких базуватимуться всі інші проекти, пов’язані з експлуатацією бази даних. У наведених вище схемах шари [DAO1] та [DAO2] мають однаковий інтерфейс, тому 24 конфігурації обох вищезазначених архітектур будуть тестуватися за допомогою єдиного тестового класу [JUnitTestsDao]. Після перевірки цих архітектур труднощів більше не виникає:
- проект Maven з публікації бази даних у мережі базується на цих двох архітектурах. Отже, тут також існує 24 можливі конфігурації;
- проект Maven із забезпечення безпеки доступу до веб-сервісу базується на попередньому проекті і також має 24 можливі конфігурації;
- нарешті, проект Maven, що дозволяє здійснювати міждоменні запити до захищеного веб-сервісу, базується на попередньому проекті і також має 24 можливі конфігурації;
Дослідження проводиться з використанням SGBD, MySQL5 та реалізації Hibernate JPA. Потім здійснюється перенесення на реалізації JPA Eclipselink та OpenJPA. Потім здійснюється перенесення на інші бази даних (PostgresQL, Oracle, SQL Server, DB2, Firebird).
Цей курс призначений для початківців. Більшість використовуваних понять пояснюється. Не потрібно мати знань ані з програмування баз даних, ані з веб-програмування. Натомість необхідні ґрунтовні знання мови SQL, оскільки використовувані запити SQL не пояснюються.
Для розуміння прикладів потрібні базові знання мови Java, які можна отримати в будь-якому вступному курсі з цієї мови. Цілком достатньо перших двох розділів документа [Вступ до мови Java (1998)]. Це старий документ (1998 року, переглянутий у 2002 році), але основи там є. Для повного курсу можна прочитати величезну книгу Жана-Марі Дуду [http://www.jmdoudoux.fr/java].
Цей документ аж ніяк не є вичерпним. Він призначений лише для того, щоб надати методологію та коди, які можна повторно використовувати в подібних контекстах. Документ написано таким чином, щоб його можна було читати без комп’ютера під рукою. Тому наведено багато знімків екрана.
Хоча цей документ не охоплює всіх можливостей мови Java та всіх сфер її застосування, його можна використовувати як навчальний посібник з мови. Якщо початківець пройде цей документ хоча б частково, він досягне рівня «просунутого користувача Java» як у використанні мови, так і у роботі з фреймворком Spring. Після цього він зможе продовжити своє навчання Java за допомогою таких праць:
- [Вступ до Spring MVC та Thymeleaf на прикладі (2015)], що продовжує вивчення екосистеми Spring, представляючи її напрямок «веб-програмування MVC»;
- [Приклад клієнт-серверної архітектури — AngularJS 1.x / Spring 4 (2014)]], що описує веб-архітектуру «клієнт/сервер», де клієнт реалізовано за допомогою фреймворку [AngularJS], а сервер — за допомогою [Spring MVC];
- [Вступ до Java EE з використанням IDE NetBeans та сервера додатків GlassFish (2012)], який відходить від екосистеми Spring на користь веб-архітектури, заснованої на JSF (Java Server Faces) та EJB (Enterprise Java Bean);
- [Вступ до програмування планшетів Android за допомогою Android Studio (2016)], що описує архітектуру «клієнт-сервер», де клієнтом є планшет на базі Android, а сервером — веб-сервіс, реалізований за допомогою Spring MVC;
1.2. Sources
Цей документ має два основні джерела:
- [ref1] : від [Вступ до Spring MVC та Thymeleaf на прикладі (2015]. Цей документ повторює роботу, виконану та представлену в [ref1], але з іншою базою даних. Простіше кажучи, він виводить її з контексту веб-програмування за допомогою Spring (MVC). Оскільки я виявив, що код та методологія, використані в [ref1] для публікації бази даних у мережі, можуть бути використані повторно, я вирішив створити окремий документ;
- [ref2] : від [Персистентність у Java 5 на практиці (2007)];
Для більш глибокого вивчення Spring можна скористатися такими джерелами:
- довідковий документ фреймворку Spring [http://docs.spring.io/spring/docs/current/spring-framework-reference/pdf/spring-framework-reference.pdf];
- численні навчальні матеріали щодо Spring можна знайти за посиланнями URL та [http://spring.io/guides];
- веб-сайт [developpez.com], присвячений Spring [http://spring.developpez.com/];
- посібник [http://www.tutorialspoint.com/spring/spring_tutorial.pdf];
Читач, який має недостатні знання SQL, зможе опанувати основи за допомогою книги [Introduction au langage SQL avec le SGBD Firebird] за посиланням URL [http://tahe.developpez.com/divers/sql-firebird/].
1.3. Використані інструменти
Наведені нижче приклади було протестовано в такому середовищі:
- комп’ютер із Windows 8.1 Pro 64-біт;
- JDK 1.8 (параграф 23.1);
- IDE Spring Tool Suite 3.6.3 (параграф 1);
- браузер Chrome (інші браузери не використовувалися);
- розширення для Chrome [Advanced Rest Client] (пункт 1);
- SGBD MySQL 5.6 Community Edition (пункт 23.4);
- SGBD SQL Server 2014 Express (параграф 23.9);
- SGBD PostgreSQL 9.4 (параграф 23.7);
- SGBD Oracle Express 11g, версія 2 (параграф 23.6);
- SGBD IBM DB2 Express-C 10.5 (параграф 23.8);
- SGBD Firebird 2.5.4 (параграф 23.10);
- клієнти EMS Manager своїх шести SGBD (параграф 23.5);
Зверніть увагу на JDK 1.8. В одному з прикладів використання використовується метод з пакета [java.lang] Java 8.
Більшість прикладів — це проекти Maven, які можна відкривати як у IDE Eclipse, так і в IntellijIDEA та NetBeans. Далі наведені знімки екрана з IDE Spring Tool Suite — варіанту Eclipse.
1.4. Приклади
Приклади доступні за посиланням URL [http://tahe.developpez.com/java/spring-database] у вигляді файлу zip, який можна завантажити.
![]() |
- у [1] — папки з прикладами;
- у [2] папка [spring-core] містить навчальні проекти Spring;
- у [3] папка [spring-database-config] містить проекти конфігурації JDBC та JPA для шести баз даних;
![]() |
- у [4] — конфігурація Oracle з SGBD. У ній містяться три папки:
- [databases] містить скрипти SQL для створення двох баз даних, що використовуються в документі;
- [jdbc-driver] містить драйвер Oracle JDBC, а також скрипт для його встановлення у локальному репозиторії Maven;
- [eclipse] містить [5] чотири проекти конфігурації Oracle:
- [oracle-config-jdbc] налаштовує рівень доступу JDBC до SGBD;
- [oracle-config-jpa-hibernate] налаштовує рівень JPA для доступу до SGBD із використанням постачальника JPA Hibernate;
- [oracle-config-jpa-eclipselink] налаштовує рівень JPA для доступу до SGBD із використанням постачальника JPA Eclipselink;
- [oracle-config-jpa-openjpa] налаштовує рівень доступу JPA до SGBD за допомогою постачальника JPA OpenJPA;
- у [6] папка [eclipse config / launch configurations] містить конфігурації виконання, які користувач зможе імпортувати в Eclipse, щоб потім адаптувати їх до власного середовища;
![]() |
- у [7], папка [spring-database-generic] містить весь код доступу до SGBD, спільний для шести SGBD та трьох постачальників JPA;
- у [8], [spring-jdbc] містить чотири проекти, які включають API, JDBC, а також Spring JDBC;
- у [9] проект [spring-jpa / spring-jpa-generic] використовує шар JPA для доступу до бази даних. Проєкти [generic-create-db*] — це проєкти JPA, що дозволяють створювати бази даних, які використовуються рівнем JPA;
![]() |
-
у [10] папка [spring-webjson] містить проекти, які надають доступ до бази даних у веб-середовищі;
- [spring-webjson-server-jdbc-generic] — це веб-сервіс, який надає доступ до бази даних, до якої звертається Spring JDBC;
- [spring-webjson-server-jpa-generic] — це веб-сервіс, що надає доступ до бази даних, до якої звертається Spring JPA;
- [spring-webjson-client-generic] — це єдиний клієнт, що забезпечує доступ до обох попередніх веб-сервісів;
-
у [11] папка [spring-security] містить проекти, які надають доступ до бази даних у мережі з захищеним доступом;
- [spring-security-server-jdbc-generic] — це захищений веб-сервіс, який надає доступ до бази даних, до якої звертається Spring JDBC;
- [spring-security-server-jpa-generic] — це захищений веб-сервіс, що надає доступ до бази даних, до якої здійснюється доступ за допомогою Spring JPA;
- [spring-security-client-generic] — це єдиний клієнт, що забезпечує доступ до обох вищезазначених захищених веб-сервісів;
-
у [12] папка [spring-cors] містить проекти, які надають доступ до бази даних у мережі з безпечним доступом, що дозволяє здійснювати міждоменні запити, наприклад, з коду JavaScript браузера;
- [spring-cors-server-jdbc-generic] — це захищений веб-сервіс, що забезпечує міждоменний доступ і надає доступ до бази даних, до якої звертається Spring JDBC;
- [spring-cors-server-jpa-generic] — це захищений веб-сервіс, що забезпечує міждоменний доступ і надає доступ до бази даних, до якої здійснюється доступ за допомогою Spring JPA;
- [spring-cors-client-generic] — це веб-додаток, що дозволяє здійснювати запити до двох попередніх веб-сервісів;












