Что такое hibernate

hibernate5 tutorial

В этой статье я постараюсь максимально просто объяснить Вам что такое hibernate фреймворк:

  • что он из себя представляет;
  • как пользоваться hibernate;
  • CRUD операции на примере простой таблицы.

Все вышеперечисленное закрепим примером. А для начала постараемся вникнуть в теорию.

Hibernate — это библиотека, которая предназначена для задач объектно-реляционного отображения. Примерно такое описание будет в википедии. Если простыми словами —  hibernate позволяет разработчику работать с базой данных не напрямую, как мы это делали с помощью библиотеки JDBC в статье Работа с базой данных, а  с помощью представления таблиц баз данных в виде классов java.

Чтобы до конца понять дебри терминов давайте разберем что такое JPAJava Persistance API.

JPA —  спецификация, которая дает возможность сохранять в удобном виде Java-объекты в базе данных. Hibernate — это одна из самых популярных реализаций этой спецификации. Вот такая вот драма. Данные термины даны только в ознакомительных целях так как очень часто запутывают и пугают начинающих разработчиков.

Как это работать с базой данных через классы java? Если Вы открыли эту статью, то наверняка уже подключали базу данных к своему приложению и работали с ней. Если нет — то настоятельно советую прочитать цикл статей Java WEB, в которых подробно описано как создать веб приложение на чистой Java. А если я прав, и Вы уже знакомы с подключением базы данных, то наверняка работали с ней таким образом: создавали объект, который отображает таблицу базы данных. Например таблицу users с полями:

  • id;
  • name;
  • email;
  • password.

Потом писали метод подключения к базе, возможно даже пул соединений. Далее был DAO класс в котором делался запрос в базу, доставались или создавались данные, распарсивали их и подавали в виде списка или объекта примерно вот таким образом:

Код   
  1. public Article getArticleById(int id) {
  2.         Article article = null;
  3.         Connection connection = ConnectionPool.getInstance().getConnection();
  4.         try {
  5.             PreparedStatement pr = connection.prepareStatement("select id, title, body, "
  6.                     + "category_id, users_id from article where id=?");
  7.             pr.setInt(1, id);//то, что нужно вставить вместо первого знака вопроса
  8. //можно было бы написать "select id, title, body, " + "category_id, users_id from article where id="+id в запросе
  9. //но в целях безопасности советую подставлять значение через метод сет.
  10.             ResultSet rs = pr.executeQuery();
  11.             if (rs.next()){
  12.                 article = new Article();
  13.                 article.setId(rs.getInt(1));
  14.                 article.setTitle(rs.getString(2));
  15.                 article.setBody(rs.getString(3));
  16.                 Category category = new Category();
  17.                 category.setId(rs.getInt(4));
  18.                 article.setCategory(category);
  19.                 Users user = new Users();
  20.                 user.setId(rs.getInt(5));
  21.                 article.setUsers(user);
  22.             }
  23.         } catch (SQLException e) {
  24.             // TODO Auto-generated catch block
  25.             e.printStackTrace();
  26.         }
  27.         try {
  28.             connection.close();
  29.         } catch (SQLException e) {
  30.             // TODO Auto-generated catch block
  31.             e.printStackTrace();
  32.         }
  33.         return article;
  34.     }

Hibernate дает Вашей разработке приложений новые инструменты: теперь вместо кучи ненужного кода нужно просто создать класс-сущность базы данных, пометить его специальным аннотациями и фреймворк все сделает за Вас.

Это называется ORMObject Relational Mapping. Вам всего лишь нужно создать классы, которые соответствуют таблицам в базе данных, и написать методы, которые Вы хотите сделать с данными (получить, удалить, создать, обновить). Hibernate сам генерирует SQL запрос и выполняет его. Причем, ему не важно какую базу данных Вы используете. Это дает возможность переключать базы данных и не заботиться о том, что код не будет работать.

С теорией закончили. Теперь давайте узнаем как подключить Hibernate, мапить классы и делать простые запросы.

Начнем с нуля. Создадим простое Maven приложение. Если Вы используете Eclipse: File->New->Maven project.

new simple maven project

Не забудьте проставить галочку возле Create a simple project. Даем нашему проекту название:

hibernate project creation

Далее нужно подключить библиотеку hibernate, JPA и драйвера к базе данных к нашему проекту.  В данном примере я использую Postgresql, но разницы не будет никакой если Вы будете использовать другую базу данных. Я укажу место, где нужно будет сделать поправки.

После подключения зависимостей мой файл pom.xml выглядит так:

Код   
  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.javamaster</groupId>
  5. <artifactId>hibernate-tutorial</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <dependencies>
  8. <dependency>
  9. <groupId>javax</groupId>
  10. <artifactId>javaee-api</artifactId>
  11. <version>7.0</version>
  12. </dependency>
  13. <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
  14. <dependency>
  15. <groupId>org.hibernate</groupId>
  16. <artifactId>hibernate-core</artifactId>
  17. <version>5.3.0.Final</version>
  18. </dependency>
  19. <!-- https://mvnrepository.com/artifact/postgresql/postgresql -->
  20. <dependency>
  21. <groupId>postgresql</groupId>
  22. <artifactId>postgresql</artifactId>
  23. <version>9.1-901-1.jdbc4</version>
  24. </dependency>
  25. </dependencies>
  26. </project>

 

Теперь нужно придумать с чем будет работать наше приложение. Предлагаю использовать пример, который я описал выше. В этой ознакомительной статье с Hibernate я покажу работу этого фреймворка только с одной таблицей. Создадим в нашей постгрес базу данных hibernate_tutorial и в этой базе создадим таблицу users.

psql shell

С этим, думаю, проблем не будет.

Теперь создадим класс Users в котором будут поля, геттеры, сеттеры, методы equals, hashCode, toString.

Код   
  1. public class Users {
  2.    
  3.     private Integer id;
  4.    
  5.     private String name;
  6.    
  7.     private String email;
  8.    
  9.     private String password;
  10.  
  11.     public Integer getId() {
  12.         return id;
  13.     }
  14.  
  15.     public void setId(Integer id) {
  16.         this.id = id;
  17.     }
  18.  
  19.     public String getName() {
  20.         return name;
  21.     }
  22.  
  23.     public void setName(String name) {
  24.         this.name = name;
  25.     }
  26.  
  27.     public String getEmail() {
  28.         return email;
  29.     }
  30.  
  31.     public void setEmail(String email) {
  32.         this.email = email;
  33.     }
  34.  
  35.     public String getPassword() {
  36.         return password;
  37.     }
  38.  
  39.     public void setPassword(String password) {
  40.         this.password = password;
  41.     }
  42.  
  43.     @Override
  44.     public int hashCode() {
  45.         final int prime = 31;
  46.         int result = 1;
  47.         result = prime * result + ((email == null) ? 0 : email.hashCode());
  48.         result = prime * result + ((id == null) ? 0 : id.hashCode());
  49.         result = prime * result + ((name == null) ? 0 : name.hashCode());
  50.         result = prime * result + ((password == null) ? 0 : password.hashCode());
  51.         return result;
  52.     }
  53.  
  54.     @Override
  55.     public boolean equals(Object obj) {
  56.         if (this == obj)
  57.             return true;
  58.         if (obj == null)
  59.             return false;
  60.         if (getClass() != obj.getClass())
  61.             return false;
  62.         Users other = (Users) obj;
  63.         if (email == null) {
  64.             if (other.email != null)
  65.                 return false;
  66.         } else if (!email.equals(other.email))
  67.             return false;
  68.         if (id == null) {
  69.             if (other.id != null)
  70.                 return false;
  71.         } else if (!id.equals(other.id))
  72.             return false;
  73.         if (name == null) {
  74.             if (other.name != null)
  75.                 return false;
  76.         } else if (!name.equals(other.name))
  77.             return false;
  78.         if (password == null) {
  79.             if (other.password != null)
  80.                 return false;
  81.         } else if (!password.equals(other.password))
  82.             return false;
  83.         return true;
  84.     }
  85.  
  86.     @Override
  87.     public String toString() {
  88.         return "Users [id=" + id + ", name=" + name + ", email=" + email + ", password=" + password + "]";
  89.     }
  90.    
  91.    
  92.  
  93. }

 

Ничего особенного в этом классе нет: это простой объект, который Вы видели много раз. Если Вы когда-нибудь слышали или видели аббревиатуру POJOPlain Old Java Object то это имелся ввиду именно такой класс. Старый простой объект java. Для того, чтобы этот класс стал сущностью базы данных нужно добавить к нему немного аннотаций.

Перед объявлением класса нужно добавить аннотацию @Entity — которая укажет, что данный класс является сущностью. Это часть спецификации JPA. Далее над классом нужно добавить еще одну аннотацию — @Table. Если Ваш класс совпадает с именем таблицы, то ничего добавлять не нужно. Но, в данной аннотации есть атрибут name в значении которого можно указать имя таблицы в базе данных, которую отображает класс. Поля класса нужно пометить аннотацией @Column в атрибут которой можно также поместить имя поля в таблице базы данных. Отдельного внимания заслуживает поле Id. Для него есть отдельная аннотация @Id. Для генерируемого значение важно указать аннотацию @GeneratedValue в атрибут которой нужно указать стратегию генерируемого значение. JPA поддерживает 3 стратегии генерации ключа. Вам же нужно выбрать стратегию в зависимости от того, как Вы генерируете айди в своей базе данных. Чтобы не усложнять и так запутанную тему мы выберем стратегию GenerationType.IDENTITY которая укажет, что мы генерируем это значение автоматически.

Код   
  1. import javax.persistence.*;
  2.  
  3. @Table(name = "users")
  4. public class Users {
  5.  
  6.     @Id
  7.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  8.     private Integer id;
  9.  
  10.     @Column(name = "name")
  11.     private String name;
  12.  
  13.     @Column(name = "email")
  14.     private String email;
  15.  
  16.     @Column(name = "password")
  17.     private String password;
  18.  
  19.     public Integer getId() {
  20.         return id;
  21.     }
  22.  
  23.     public void setId(Integer id) {
  24.         this.id = id;
  25.     }
  26.  
  27.     public String getName() {
  28.         return name;
  29.     }
  30.  
  31.     public void setName(String name) {
  32.         this.name = name;
  33.     }
  34.  
  35.     public String getEmail() {
  36.         return email;
  37.     }
  38.  
  39.     public void setEmail(String email) {
  40.         this.email = email;
  41.     }
  42.  
  43.     public String getPassword() {
  44.         return password;
  45.     }
  46.  
  47.     public void setPassword(String password) {
  48.         this.password = password;
  49.     }
  50.  
  51.     @Override
  52.     public int hashCode() {
  53.         final int prime = 31;
  54.         int result = 1;
  55.         result = prime * result + ((email == null) ? 0 : email.hashCode());
  56.         result = prime * result + ((id == null) ? 0 : id.hashCode());
  57.         result = prime * result + ((name == null) ? 0 : name.hashCode());
  58.         result = prime * result + ((password == null) ? 0 : password.hashCode());
  59.         return result;
  60.     }
  61.  
  62.     @Override
  63.     public boolean equals(Object obj) {
  64.         if (this == obj)
  65.             return true;
  66.         if (obj == null)
  67.             return false;
  68.         if (getClass() != obj.getClass())
  69.             return false;
  70.         Users other = (Users) obj;
  71.         if (email == null) {
  72.             if (other.email != null)
  73.                 return false;
  74.         } else if (!email.equals(other.email))
  75.             return false;
  76.         if (id == null) {
  77.             if (other.id != null)
  78.                 return false;
  79.         } else if (!id.equals(other.id))
  80.             return false;
  81.         if (name == null) {
  82.             if (other.name != null)
  83.                 return false;
  84.         } else if (!name.equals(other.name))
  85.             return false;
  86.         if (password == null) {
  87.             if (other.password != null)
  88.                 return false;
  89.         } else if (!password.equals(other.password))
  90.             return false;
  91.         return true;
  92.     }
  93.  
  94.     @Override
  95.     public String toString() {
  96.         return "Users [id=" + id + ", name=" + name + ", email=" + email + ", password=" + password + "]";
  97.     }
  98.    
  99.    
  100.  
  101. }

Теперь на подобии коннектора подключений нужно указать настройки hibernate, чтобы библиотека знала с какой базой мы работаем, логин, пароль и тип базы. Создадим класс HibernateUtill и добавим в него немного магии.

Код   
  1. import java.util.HashMap;
  2. import java.util.Map;
  3.  
  4. import org.hibernate.SessionFactory;
  5. import org.hibernate.boot.Metadata;
  6. import org.hibernate.boot.MetadataSources;
  7. import org.hibernate.boot.registry.StandardServiceRegistry;
  8. import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
  9. import org.hibernate.cfg.Environment;
  10.  
  11. public class HibernateUtil {
  12.  
  13.     private static StandardServiceRegistry registry;
  14.     private static SessionFactory sessionFactory;
  15.  
  16.     public static SessionFactory getSessionFactory() {
  17.         //реализация синглтона. Если объекта нет - создаем, если есть просто возвращаем
  18.         if (sessionFactory == null) {
  19.             try {
  20.                 StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder();
  21.  
  22.                 //стандартные настройки для хибернат
  23.                 //для тех, кто использует другую базу данных нужно заметить поле DRIVER, DIALECT и кусок URL легко гуглятся под любую базу
  24.                 Map<String, String> settings = new HashMap<>();
  25.                 settings.put(Environment.DRIVER, "org.postgresql.Driver");
  26.                 settings.put(Environment.URL, "jdbc:postgresql://localhost:5432/hibernate_tutorial");
  27.                 settings.put(Environment.USER, "postgres");
  28.                 settings.put(Environment.PASS, "postgres");
  29.                 settings.put(Environment.DIALECT, "org.hibernate.dialect.PostgreSQL9Dialect");
  30.  
  31.                 registryBuilder.applySettings(settings);
  32.  
  33.                 registry = registryBuilder.build();
  34.  
  35.                 MetadataSources sources = new MetadataSources(registry);
  36.                                 sources.addAnnotatedClass(Users.class);
  37.                 Metadata metadata = sources.getMetadataBuilder().build();
  38.  
  39.                 sessionFactory = metadata.getSessionFactoryBuilder().build();
  40.  
  41.             } catch (Exception e) {
  42.                 e.printStackTrace();
  43.                 if (registry != null) {
  44.                     StandardServiceRegistryBuilder.destroy(registry);
  45.                 }
  46.             }
  47.         }
  48.         return sessionFactory;
  49.     }
  50.  
  51.     public static void close() {
  52.         if (registry != null) {
  53.             StandardServiceRegistryBuilder.destroy(registry);
  54.         }
  55.     }
  56.  
  57. }

Это конфигурационный файл, который позволяет настроить hibernate без xml. Я стараюсь не программировать с xml там, где это позволяют новые возможности.

Далее создадим простой класс-сервис по CRUD операциям с сущностью Users.

Код   
  1. import java.util.List;
  2.  
  3. import javax.persistence.criteria.CriteriaQuery;
  4. import javax.transaction.Transactional;
  5.  
  6. import org.hibernate.Session;
  7.  
  8. public class UsersCRUD {
  9.    
  10.     public void save(Users users) {
  11.         Session session = HibernateUtil.getSessionFactory().openSession(); //открываем сессию
  12.         session.beginTransaction();
  13.         session.save(users); //пользуемся ее методами
  14.         session.flush();
  15.         session.close();
  16.     }
  17.    
  18.     public void delete(Users users) {
  19.         Session session = HibernateUtil.getSessionFactory().openSession();
  20.         session.beginTransaction();
  21.         session.delete(users);
  22.         session.flush();
  23.         session.close();
  24.     }
  25.    
  26.     public List<Users> getAll(){
  27.         Session session = HibernateUtil.getSessionFactory().openSession();
  28.         return session.createCriteria(Users.class).list();
  29.     }
  30.    
  31.     public Users getById(Integer id) {
  32.         Session session = HibernateUtil.getSessionFactory().openSession();
  33.         Users users = session.get(Users.class, id);
  34.         return users;
  35.     }
  36.  
  37. }

В данном примере я не буду использовать язык HQL дабы не усложнять материал. Только уточню, что с помощью данного фреймворка можно работать с базой данных очень большим количеством способов, выбор которых падает на программиста и предметную область.

Теперь осталось протестировать наши методы.

Код   
  1. public class Main {
  2.  
  3.     public static void main(String[] args) {
  4.         UsersCRUD usersCRUD = new UsersCRUD();
  5.         Users users1 = new Users();
  6.         users1.setName("John");
  7.         users1.setEmail("connor_john@gmail.com");
  8.         users1.setPassword("somepswd123");
  9.         usersCRUD.save(users1);
  10.        
  11.         Users users2 = new Users();
  12.         users2.setName("Sara");
  13.         users2.setEmail("sarra_mother@gmail.com");
  14.         users2.setPassword("qwerty123");
  15.         usersCRUD.save(users2);
  16.        
  17.         usersCRUD.getAll().forEach(it->System.out.println(it));
  18.        
  19.         Users userWithId1 = usersCRUD.getById(5);
  20.         System.out.println(userWithId1);
  21.        
  22.         usersCRUD.delete(userWithId1);
  23.        
  24.         usersCRUD.getAll().forEach(it->System.out.println(it));
  25.  
  26.     }
  27.  
  28. }

Ну и результат запуска приложения:

что такое hibernate

Надеюсь, Вы поняли что такое hibernate и JPA и какие возможности открывает данный фреймворк для программиста. Это лишь малая часть того, что умеет этот инструмент. Но для ознакомления и первого впечатления должно хватить.

Код с примера находится здесь: https://github.com/caligula95/hibernate-tutorial

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *