MyBatis як швидша альтернатива Hibernate
У Java співтоваристві Hibernate framework де-факто вважається стандартом для зручної роботи з базою даних. Розробнику важко вибрати інший фреймфорк, тому що часом він не знає про існування альтернатив. У цій статті я проведу курс молодого бійця для роботи з MyBatis framework. Повністю охопити весь framework не вийде, але інформації буде достатньо, щоб побачити переваги і слабкі сторони даного framework'а і почати працювати з MyBatis.
MyBatis не реалізує JPA спікання, а є альтернативою JPA. Основна відмінність MyBatis від Hibernate - це те, як виробляється мапінг об'єктів. Hibernate карта таблиці БД на суті, даючи нам доступ до даних. Для отримання даних Hibernate генерує SQL запити, а запити, що генеруються, хороші до пори - до часу, а потім вони з'їдають купу часу, стають громіздкими і не керованими. MyBatis мапиться не так на таблиці, але в SQL запити, формування запитів відповідає розробник і тільки від нього залежатиме як швидко працювати додаток.
З преамбулою закінчили, тепер можна перейти безпосередньо до створення невеликого проекту з використанням MyBatis, щоб познайомитися з ним ближче. Не буду оригінальним, зробимо декілька запитів до БД з використанням MyBatis. У прикладі використовуватиму СУБД MySQL, а ви можете використовувати будь-яку іншу СУБД, яка вам до вподоби.
Створимо БД mybatis:
Створимо таблиці subscriber, tariff, payments:
Найсумніше позаду — у нас є БД, з якої ми отримуватимемо дані, тепер приступимо безпосередньо до роботи з MyBatis. Для початку нам потрібна бібліотека MyBatis. Для отримання бібліотеки ми будемо використовувати maven, необхідно додати залежність до налаштування проекту (pom.xml):
На момент написання статті останняверсія MyBatis 3.2.8
Після того, як бібліотека успішно завантажилася, необхідно налаштувати підключення до БД. Налаштування здійснюються у конфігураційному файлі mybatis-config.xml.
Нижче наведено листинг конфігураційного файлу:
У лістингу вище я вказав 3 мапера - вся взаємодія з БД буде здійснюватися через мапери і чим детальніше ви розумітимете як працювати з маперами і формувати запити, тим більш продуктивнішими будуть ваші додатки.
Для коректної роботи з MyBatis необхідно створити інтерфейс мапера в якому будуть зумовлені методи, які будуть використовуватися і xml файл налаштувань в якому будуть описані запити sql, правила їх мапінгу на об'єкти і тп.
Створимо інтерфейс kz.jazzsoft.mapper.SubscriberMapper:
У цьому інтерфейсі ми визначили два методи:
1. getSubscriberById - поверне одного користувача за id;
2. getSubscriber - поверне список користувачів;
Але щоб дані методи заробили необхідно створити xml маппер з sql запитами.
Я пропустив ще один момент, який необхідно було зробити - це створити класи beanEntity, на які ми будемо мапіти результати виконання запитів.
Можна відразу подивитися, як працює код, для цього необхідно підключитися до БД та ініціалізувати потрібний мапер, а поки що він у нас один (SubscriberMapper). Створимо клас, у якому працюватимемо:
Запити виконалися і ми маємо об'єкти, з якими ми можемо працювати. Ви можете подивитися, що об'єкти мають id та інші поля заповнені, але не всі. Тут є один аспект, якщо колонка в БД має таке саме ім'я як змінна, то вона автоматично змапиться на неї. Щоб розширити можливості мапінгу і створювати складні структури в арсеналі MyBatis є тег ResultMap, якийдозволяє настроювати довільний мапінг. Робити зв'язки one-to-one і one-to-many.
ResultMap є описом правил зв'язку полів EntityBean з колонками з таблиць. Приклад для Subscriber:
У результаті мапер для Subscriber виглядатиме так:
Зв'язок one-to-one здійснюється не складніше за приклад вище. Але нам спочатку необхідно буде описати наступний мапер Tariff. Через нього ми отримуватимемо дані для пов'язаного поля в Subscriber.
Створюємо сутність Tariff:
Створюємо інтерфейс мапера TariffMapper, нам знадобиться лише один метод:
Тепер можна додати Subscriber з Tariff в SubscriberMaper, в resultMap необхідно додати правило зв'язку:
Необхідно замінити даний resultMap і можна буде дізнатися на якому тарифному плані у нас знаходиться Абонент (Subscriber)
Додамо до Абонента (Subscriber) список його платежів (Payments) (one-to-many):
Для початку необхідно створити EntityBean Payment:
Тепер потрібно створити інтерфейс мапера PaymentMapper, він буде простий. Тільки один метод отримання списку платежів за ID користувача.
Необхідно створити xml мапер:
Отриманий resultMap замінюємо в SubscriberMapper і можна переглянути всі платежі користувача. Але на цьому все найцікавіше лише починається.
MyBatis має функціонал, який дозволяє формувати SQL запити динамічно в залежності від параметрів, які були в нього передані. Наприклад нам немає необхідності створювати купу sql на кожну дію (вибірки з однієї таблиці, але за різними параметрами), можна відбутися одним методом, який фільтруватиме тих же абонентів по кількох колонках або взагалі не фільтруватиме і поверне всіх залежно від вхідних даних, але про все по порядку.
Для динамічного формування SQL запитів у арсеналі MyBatis є достатньо компонентів на вирішення більшості завдань. Розглядати всі ми не будемо, тому що їх досить багато і їх можна комбінувати тощо. Для прикладу розглянемо IF оператор, більше інформації можна прочитати в офіційному посібнику: mybatis.github.io/mybatis-3/dynamic-sql.html
У наведеному вище запиті виконується перевірка, на те що об'єкт у Map за ключом descr не null, тоді в запит буде додано рядок в блоці if і таких блоків може бути скільки завгодно, вони можу бути вкладеними.
MyBatis при розумному використанні може дати відчутний приріст швидкості роботи програми. Може здатися страшно писати самому запити і правила мапінгу, але це тільки здається, Hibirnate теж не така проста.
Немає єдиного універсального рішення, яке підійшло б усім, у кожному виборі потрібен чіткий розрахунок. MyBatis можна використовувати спільно з Hibernate там, де це дійсно потрібно, а це зможете визначити тільки ви.