У цій статті ви познайомитеся з одним з найбільш популярних enterprise-фреймворків для Java і створіть свій перший додаток на Hibernate. Ніколи не чули про Hibernate? Може, чули про нього, але не користувалися? Чи намагалися розпочати, але не вийшло? У всіх трьох випадках - ласкаво просимо під кат:)
Всім привіт! У цій статті я розповім про основні особливості фреймворку Hibernate і допоможу вам написати свій перший міні-додаток. Для цього нам знадобляться:
Як бачите, нічого складного. 6 класів + 1 файл із конфігами. Для початку створимо новий maven-проект в Intellij Idea. File -> New Project. З пропонованих типів проектів вибирайте Maven і переходьте далі.
Apache Maven — фреймворк для автоматизації складання проектів на основі опису їхньої структури у файлух мовою POM. Вся структура вашого проекту буде описана у файлі pom.xml, який IDEA сама створить у корені вашого проекту. У налаштуваннях проекту потрібно буде вказати параметри Maven - groupId і artifactId. Зазвичай у проектах групивизначається назва організації або підрозділу, туди записують доменне ім'я організації або сайту проекту. У свою чергу artifactId – назва проекту. Для groupdId можете вказати
На останньому екрані просто підтвердьте введені дані.
Отже, проект ми створабо, залишилося всього нічого - написати код і змусити його працювати :) Перш за все, якщо ми хочемо створити додаток, що працюють з базою даних - нам безумовно не обійтися без бази даних! Качаємо PostgreSQL звідси(Я використовую 9 версію). PostgreSQL має створений за замовчуванням користувач 'postgres', пароль для нього вам потрібно буде придумати при установці. Не забувайте пароль, він нам знадобиться згодом! (Взагалі, користуватися дефолтною БД у додатках - bad practice, але з метою скоротити обсяг геморою зі створенням своєї БД обійдемося їй). Якщо ви не товаришуєте з командним рядком та SQL-запитами, є хороша новина. Intellij IDEA надає цілком придатний інтерфейс користувача для роботи з БД. Виглядає він так:
(Знаходиться на правій бічній панелі IDEA, вкладка Database) Для створення підключення натисніть "+", виберіть нашого провайдера (PostgeSQL). Заповніть поля з користувачем, іменем БД (і те й інше – postgres) та введіть пароль, який задали під час встановлення PostgreSQL. При необхідності – завантажте драйвер Postgres, це можна зробити на цій самій сторінці. Натисніть "Test Connection", щоб перевірити, чи з'єднання з БД встановлено. Якщо бачите напис "Successful" - їдемо далі. Тепер створимо потрібні таблиці. Усього їх буде дві - users і autos. Параметри для таблиці users:
Зверніть увагу, що id є первинним ключем (Primary Key). Якщо не знаєте, що таке первинний ключ в SQL - гугл, це важливо. Налаштування для таблиці autos:
Для автомобілів потрібно налаштувати Foreign Key — зовнішній ключ. Він буде пов'язувати наші таблиці. Раджу почитати про нього докладніше; якщо говорити дуже просто - він посилається на зовнішню таблицю, у разі на users. Якщо машина належить користувачеві з id=1, то полі user_id таблиці autos в неї буде 1. Так ми у нашому додатку пов'язуємо користувачів зі своїми автомобілями. У нашій таблиці autos роль зовнішнього ключа виконуватиме поле user_id. Воно буде посилатися на поле ID таблиці users.
Таким чином, ми створабо базу даних із двома таблицями. Залишилося зрозуміти, як керувати з Java-коду. Почнемо ми з файлу pom.xml, в якому нам необхідно підключити необхідні бібліотеки (на мові Maven вони називаються dependencies - "залежності"). Усі бібліотеки зберігаються у центральному репозиторії Maven. Ті з них, які ви вкажете в pom.xml, ви можете використовувати у проекті. Ваш pom.xml повинен мати такий вигляд:
Нічого складного, як бачите. Ми додали всього 2 залежності - для використання PostgreSQL та Hibernate.
Тепер перейдемо до Java-коду. Створіть усі необхідні пакети та класи проекту. Для початку, нам знадобляться моделі даних – класи
Hibernate.cfg.xml зачитується тут: ![Ваш перший додаток на Hibernate - 13]()
Спробуймо перейменувати нашого користувача. Очистимо таблицю users та виконаємо код
А якщо видалити користувача? Очистимо таблицю users (autos очиститься сама) та виконаємо код
Всім привіт! У цій статті я розповім про основні особливості фреймворку Hibernate і допоможу вам написати свій перший міні-додаток. Для цього нам знадобляться:
- Intellij Idea Ultimate Edition;
Качаємо з офіційного сайту та активуємо 30-денну пробну версію. - PostgeSQL - одна з найпопулярніших сучасних систем управління базами даних (СУБД);
- Maven (вже зашитий в IDEA);
- Трошки терпіння.
Що таке Hibernate?
Це одна з найбільш популярних реалізацій ORM-моделі. Об'єктно-реляційна модель описує відносини між програмними об'єктами та записами у БД. Звичайно, функціонал Hibernate дуже широкий, але ми зупинимося на найпростіших функціях. Наша мета: створити CRUD-додаток (Create,Read,Update,Delete), який вмітиме:- Створювати користувачів (User), а також шукати їх у базі даних за ID, оновлювати їх у базі, а також видаляти з бази.
- Надавати користувачам об'єкти автомобілів (Auto). Створювати, редагувати, знаходити та видаляти автомобілі з бази даних.
- Крім того, додаток повинен автоматично видаляти "безхазяйні" автомобілі з БД. Тобто. при видаленні користувача, всі його автомобілі також повинні бути видалені з БД.
Як бачите, нічого складного. 6 класів + 1 файл із конфігами. Для початку створимо новий maven-проект в Intellij Idea. File -> New Project. З пропонованих типів проектів вибирайте Maven і переходьте далі.
Apache Maven — фреймворк для автоматизації складання проектів на основі опису їхньої структури у файлух мовою POM. Вся структура вашого проекту буде описана у файлі pom.xml, який IDEA сама створить у корені вашого проекту. У налаштуваннях проекту потрібно буде вказати параметри Maven - groupId і artifactId. Зазвичай у проектах групивизначається назва організації або підрозділу, туди записують доменне ім'я організації або сайту проекту. У свою чергу artifactId – назва проекту. Для groupdId можете вказатиcom.вашНикнейм.codegymНа роботу програми це ніяк не вплине. Для artifactId виберіть будь-яку назву проекту, що вам сподобалася. Version також можете залишити без змін.
На останньому екрані просто підтвердьте введені дані.
Отже, проект ми створабо, залишилося всього нічого - написати код і змусити його працювати :) Перш за все, якщо ми хочемо створити додаток, що працюють з базою даних - нам безумовно не обійтися без бази даних! Качаємо PostgreSQL звідси(Я використовую 9 версію). PostgreSQL має створений за замовчуванням користувач 'postgres', пароль для нього вам потрібно буде придумати при установці. Не забувайте пароль, він нам знадобиться згодом! (Взагалі, користуватися дефолтною БД у додатках - bad practice, але з метою скоротити обсяг геморою зі створенням своєї БД обійдемося їй). Якщо ви не товаришуєте з командним рядком та SQL-запитами, є хороша новина. Intellij IDEA надає цілком придатний інтерфейс користувача для роботи з БД. Виглядає він так:
(Знаходиться на правій бічній панелі IDEA, вкладка Database) Для створення підключення натисніть "+", виберіть нашого провайдера (PostgeSQL). Заповніть поля з користувачем, іменем БД (і те й інше – postgres) та введіть пароль, який задали під час встановлення PostgreSQL. При необхідності – завантажте драйвер Postgres, це можна зробити на цій самій сторінці. Натисніть "Test Connection", щоб перевірити, чи з'єднання з БД встановлено. Якщо бачите напис "Successful" - їдемо далі. Тепер створимо потрібні таблиці. Усього їх буде дві - users і autos. Параметри для таблиці users:
Зверніть увагу, що id є первинним ключем (Primary Key). Якщо не знаєте, що таке первинний ключ в SQL - гугл, це важливо. Налаштування для таблиці autos:
Для автомобілів потрібно налаштувати Foreign Key — зовнішній ключ. Він буде пов'язувати наші таблиці. Раджу почитати про нього докладніше; якщо говорити дуже просто - він посилається на зовнішню таблицю, у разі на users. Якщо машина належить користувачеві з id=1, то полі user_id таблиці autos в неї буде 1. Так ми у нашому додатку пов'язуємо користувачів зі своїми автомобілями. У нашій таблиці autos роль зовнішнього ключа виконуватиме поле user_id. Воно буде посилатися на поле ID таблиці users.
Таким чином, ми створабо базу даних із двома таблицями. Залишилося зрозуміти, як керувати з Java-коду. Почнемо ми з файлу pom.xml, в якому нам необхідно підключити необхідні бібліотеки (на мові Maven вони називаються dependencies - "залежності"). Усі бібліотеки зберігаються у центральному репозиторії Maven. Ті з них, які ви вкажете в pom.xml, ви можете використовувати у проекті. Ваш pom.xml повинен мати такий вигляд:
Нічого складного, як бачите. Ми додали всього 2 залежності - для використання PostgreSQL та Hibernate.
Userта Auto.
package models;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table (name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "name")
private String name;
//Можна не вказувати Column name, якщо воно збігається з назвою стовпця в таблиці
private int age;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Auto> autos;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
autos = new ArrayList<>();
}
public void addAuto(Auto auto) {
auto.setUser(this);
autos.add(auto);
}
public void removeAuto(Auto auto) {
autos.remove(auto);
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<Auto> getAutos() {
return autos;
}
public void setAutos(List<Auto> autos) {
this.autos = autos;
}
@Override
public String toString() {
return "models.User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
package models;
import javax.persistence.*;
@Entity
@Table(name = "autos")
public class Auto {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column (name = "model")
private String model;
//Можна не вказувати Column name, якщо воно збігається з назвою стовпця в таблиці
private String color;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
public Auto() {
}
public Auto(String model, String color) {
this.model = model;
this.color = color;
}
public int getId() {
return id;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return color + " " + model;
}
} Як бачите, класи забезпечені купою поки що незрозумілих анотацій. Почнемо з ними розбиратися. Головна для нас інструкція - @Entity (сутність). Прочитайте в ній у Вікіпедії і запам'ятайте все, це - основа основ. Ця інструкція дозволяє Java-об'єктам вашого класу бути пов'язаними з БД. Щоб клас міг бути сутністю, щодо нього пред'являються такі вимоги:
- Повинен мати порожній конструктор (
publicабоprotected); - Не може бути вкладеним, інтерфейсом або
enum; - Не може бути
finalі не може міститиfinalполів/властивостей; - Має містити хоча б одне @Id-поле.
- утримувати непусті конструктори;
- успадковуватися і бути успадкованим;
- Утримувати інші методи та реалізовувати інтерфейси.
Userбагато в чому схожий на таблицю користувачів. Є поля id, name,age. Розташовані над ними анотації пояснення особливо не потребують: і так зрозуміло, що @Id - це вказівка, що поле є ідентифікатором об'єктів цього класу. Анотація @Table над класом вказує як називається таблиця, у якому записуються об'єкти. Зверніть увагу на коментар над полем age: якщо ім'я поля в класі та таблиці збігається - можна не додавати інструкцію @Column, буде працювати і так. Що стосується зазначеного у дужках "strategy = GenerationType.IDENTITY": є кілька стратегій генерації ID. Можете погуглити, але в рамках нашої програми можна не морочитися. Головне, що id для наших об'єктів генеруватимуться автоматично, тому для id відсутній сеттер, і в конструкторі ми його теж не задаємо. Проте, чимось класUserтаки виділяється. Має список машин! Над списком висить інструкція @OneToMany. Вона означає, що одному об'єкту класу user може відповідати кілька машин. Налаштування "mappedBY" вказує на поле user класу Auto. Таким чином машини та користувачі пов'язані між собою. Налаштування orphanRemoval цілком добре перекладається з англійської - "видаляти сиріт". Якщо ми видалимо користувача з БД - всі пов'язані з ним автомобілі також будуть видалені. У свою чергу у класіAutoви побачите поле user з анотацією @ManyToOne (багатьом Auto може відповідати один User) та анотацію @JoinColumn. Вона вказує, через який стовпець у таблиці autos відбувається зв'язок із таблицею users (той самий зовнішній ключ, про який ми говорабо раніше). Після створення моделі даних настав час навчити нашу програму виконувати з цими даними операції в БД. Почнемо з утилітного класу HibernateSessionFactoryUtil. Він має лише одне завдання — створювати для нашого додатку фабрику сесій для роботи з БД (привіт, патерн "Фабрика!"). Більше він нічого не вміє.
package utils;
import models.Auto;
import models.User;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateSessionFactoryUtil {
private static SessionFactory sessionFactory;
private HibernateSessionFactoryUtil() {}
public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
try {
Configuration configuration = new Configuration().configure();
configuration.addAnnotatedClass(User.class);
configuration.addAnnotatedClass(Auto.class);
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
sessionFactory = configuration.buildSessionFactory(builder.build());
} catch (Exception e) {
System.out.println("Виняток!" + e);
}
}
return sessionFactory;
}
} У цьому вся класі ми створюємо новий об'єкт конфігурацій Configuration, і передаємо йому ті класи, які має сприймати як сутності — Userі Auto. Зверніть увагу на метод configuration.getProperties(). Які ще properties? Звідки? Properties — це параметри для роботи hibernate, зазначені у спеціальному файлі hibernate.cfg.xml.
Hibernate.cfg.xml зачитується тут: new Configuration().configure(); У ньому, як бачите, немає нічого особливого - параметри з'єднання з базою даних, і спеціальний параметр show_sql. Він потрібен для того, щоб усі sql-запити, які hibernate буде виконувати до нашої БД, виводабося в консоль. Таким чином, ви будете бачити, що конкретно робить Hibernate в кожний момент часу і позбавитеся від ефекту "магії". Далі нам знадобиться класUserDAO. (По-доброму, програмувати потрібно через інтерфейси — створити інтерфейс UserDAOта окремо його реалізацію UserDAOImpl, але для скорочення обсягу коду я опущу це. Не робіть так у реальних проектах!). DAO (data access object) - один з найпоширеніших патернів проектування, "Доступ до даних". Його сенс простий — створити у додатку шар, який відповідає лише доступ до даних, і більше нізащо. Дістати дані з БД, оновити дані, видалити дані і все. Почитайте про DAO докладніше, у роботі користуватиметеся ними постійно. Що ж вміє наш клас UserDao? Власне, як і всі DAO, він уміє лише працювати з даними. Знайти користувача по id, оновити його дані, видалити його, витягнути з БД перелік всіх користувачів чи зберегти в БД нового користувача — ось його функционал.
package dao;
import models.Auto;
import models.User;
import org.hibernate.Session;
import org.hibernate.Transaction;
import utils.HibernateSessionFactoryUtil;
import java.util.List;
public class UserDao {
public User findById(int id) {
return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(User.class, id);
}
public void save(User user) {
Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
Transaction tx1 = session.beginTransaction();
session.save(user);
tx1.commit();
session.close();
}
public void update(User user) {
Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
Transaction tx1 = session.beginTransaction();
session.update(user);
tx1.commit();
session.close();
}
public void delete(User user) {
Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
Transaction tx1 = session.beginTransaction();
session.delete(user);
tx1.commit();
session.close();
}
public Auto findAutoById(int id) {
return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(Auto.class, id);
}
public List<User> findAll() {
List<User> users = (List<User>) HibernateSessionFactoryUtil.getSessionFactory().openSession().createQuery("From User").list();
return users;
}
} Методи UserDaoсхожі один на одного. У більшості з них ми отримуємо об'єкт Session (сесія з'єднання з нашою БД) за допомогою нашої Фабрики Сесій, створюємо в рамках цієї сесії одиночну транзакцію, виконуємо необхідні перетворення даних, зберігаємо результат транзакції в БД та закриваємо сесію. Самі методи також, як бачите, досить прості. Саме DAO - "серце" нашої програми. Однак ми не будемо створювати DAO безпосередньо і викликати його методи в нашому методі main(). Вся логіка буде переміщена до класу UserService.
package services;
import dao.UserDao;
import models.Auto;
import models.User;
import java.util.List;
public class UserService {
private UserDao usersDao = new UserDao();
public UserService() {
}
public User findUser(int id) {
return usersDao.findById(id);
}
public void saveUser(User user) {
usersDao.save(user);
}
public void deleteUser(User user) {
usersDao.delete(user);
}
public void updateUser(User user) {
usersDao.update(user);
}
public List<User> findAllUsers() {
return usersDao.findAll();
}
public Auto findAutoById(int id) {
return usersDao.findAutoById(id);
}
}
Service - шар даних у додатку, що відповідає за виконання бізнес-логіки. Якщо ваша програма має виконати якусь бізнес-логіку, вона робить це через сервіси. Сервіс містить у собі UserDao, і у методах викликає методи DAO. Це може здатися вам дублюванням функцій (чому б просто не викликати методи з dao-об'єкта), але при великій кількості об'єктів і складній логіці розбиття програми на шари дає величезні переваги (це good practice, запам'ятайте цю інформацію на майбутнє і почитайте про "шари додатку "). У нас у сервісі логіка проста, а в реальних проектах методи сервісів будуть містити куди більше одного рядка коду:) Тепер у нас є все, що потрібно для роботи програми! Давайте створимо у методіmain()користувача, машини йому, зв'яжемо їх друг з одним і збережемо в БД.
import models.Auto;
import models.User;
import services.UserService;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) throws SQLException {
UserService userService = new UserService();
User user = new User("Masha",26);
userService.saveUser(user);
Auto ferrari = new Auto("Ferrari", "red");
ferrari.setUser(user);
user.addAuto(ferrari);
Auto ford = new Auto("Ford", "black");
ford.setUser(user);
user.addAuto(ford);
userService.updateUser(user);
}
} Як бачите, у таблиці users з'явився свій запис, а таблиці autos — свої. 
Спробуймо перейменувати нашого користувача. Очистимо таблицю users та виконаємо код
import models.Auto;
import models.User;
import services.UserService;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) throws SQLException {
UserService userService = new UserService();
User user = new User("Masha",26);
userService.saveUser(user);
Auto ferrari = new Auto("Ferrari", "red");
user.addAuto(ferrari);
Auto ford = new Auto("Ford", "black");
ford.setUser(user);
user.addAuto(ford);
userService.updateUser(user);
user.setName("Sasha");
userService.updateUser(user);
}
} Працює!
А якщо видалити користувача? Очистимо таблицю users (autos очиститься сама) та виконаємо код
import models.Auto;
import models.User;
import services.UserService;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) throws SQLException {
UserService userService = new UserService();
User user = new User("Masha",26);
userService.saveUser(user);
Auto ferrari = new Auto("Ferrari", "red");
user.addAuto(ferrari);
Auto ford = new Auto("Ford", "black");
ford.setUser(user);
user.addAuto(ford);
userService.updateUser(user);
user.setName("Sasha");
userService.updateUser(user);
userService.deleteUser(user);
}
} І наші таблиці абсолютно порожні (зверніть увагу на консоль, туди виведуть усі запити, які виконав Hibernate). Ви можете "грати" з додатком і спробувати всі його функції. Наприклад, створіть користувача з машинами, збережіть його в БД, подивіться який ID йому присвоєно, і спробуйте в методі main()"витягнути" користувача з БД з цього id і вивести в консоль список його машин. Звичайно, ми побачабо лише невелику частину функціональності Hibernate. Його можливості дуже широкі, і він давно є одним із промислових стандартів Java-розробки. Якщо ви хочете вивчити його у всіх подробицях – можу рекомендувати книгу "Java Persistence API та Hibernate", оглядна яку я робив в одній із минулих статей. Сподіваюся, ця стаття була корисною для читачів. Якщо у вас будуть питання - задавайте їх у коментарях, з радістю відповім :) Також не забувайте підтримати автора у конкурсі, поставивши "Подобається". А краще - "Дуже подобається" :) Успіхів у навчанні!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ