Как подключить hibernate к java проекту
Перейти к содержимому

Как подключить hibernate к java проекту

  • автор:

Не могу подключить Hibernate

Создал новый проект. Подключил Hibernate и PostgreSQL.

com.example demo 1.0-SNAPSHOT demo 17 17   org.hibernate hibernate-core 6.1.6.Final  org.postgresql postgresql 42.5.1   

Создал persistence.xml в resources/META-INF

   org.hibernate.jpa.HibernatePersistenceProvider com.example.demo.Account             

Создал POJO класс

package com.example.demo; import jakarta.persistence.*; import static jakarta.persistence.GenerationType.IDENTITY; @Entity @Table(name = "ACCOUNTS") public final class Account < @Id @GeneratedValue(strategy = IDENTITY) @Column(name = "ACC_ID") private Long id; @Column(name = "ACC_LOGIN") private String login; @Column(name = "ACC_ISDISABLED") private Boolean blocked; @Column(name = "ACC_NOTE") private String note; public Account() < >@Override public String toString() < return "Account'; > > 

Написал тестовый запрос

public class Main < public static void main(String[] args) < EntityManagerFactory emf = Persistence.createEntityManagerFactory("demo"); EntityManager em = emf.createEntityManager(); try < em.getTransaction().begin(); Account account = em.find(Account.class, 1L); System.out.println(account); em.getTransaction().commit(); >catch (Exception e) < em.getTransaction().rollback(); throw new RuntimeException(e); >finally < em.close(); emf.close(); >> > 

Но вместо данных получил ошибку:

янв. 30, 2023 12:44:03 AM org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation INFO: HHH000204: Processing PersistenceUnitInfo [name: demo] янв. 30, 2023 12:44:03 AM org.hibernate.Version logVersion INFO: HHH000412: Hibernate ORM core version 6.1.6.Final янв. 30, 2023 12:44:04 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure WARN: HHH10001002: Using built-in connection pool (not intended for production use) янв. 30, 2023 12:44:04 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001005: Loaded JDBC driver class: org.postgresql.Driver янв. 30, 2023 12:44:04 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001012: Connecting with JDBC URL [jdbc:postgresql://localhost:5432/test] янв. 30, 2023 12:44:04 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001001: Connection properties: янв. 30, 2023 12:44:04 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001003: Autocommit mode: false янв. 30, 2023 12:44:04 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections INFO: HHH10001115: Connection pool size: 20 (min=1) янв. 30, 2023 12:44:06 AM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect янв. 30, 2023 12:44:07 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@422b8438] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode. янв. 30, 2023 12:44:07 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions WARN: SQL Error: 0, SQLState: 42703 янв. 30, 2023 12:44:07 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions ERROR: Колонки start_value не найдено в этом ResultSet’’е. янв. 30, 2023 12:44:07 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PoolState stop INFO: HHH10001008: Cleaning up connection pool [jdbc:postgresql://localhost:5432/test] янв. 30, 2023 12:44:07 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections close ERROR: Connection leak detected: there are 1 unclosed connections upon shutting down pool jdbc:postgresql://localhost:5432/test янв. 30, 2023 12:44:07 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl validateConnectionsReturned ERROR: Connection leak detected: there are 1 unclosed connections Exception in thread "main" jakarta.persistence.PersistenceException: [PersistenceUnit: demo] Unable to build Hibernate SessionFactory at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1509) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1430) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:55) at jakarta.persistence.Persistence.createEntityManagerFactory(Persistence.java:80) at jakarta.persistence.Persistence.createEntityManagerFactory(Persistence.java:55) at com.example.demo.Main.main(Main.java:10) Caused by: org.hibernate.exception.SQLGrammarException: Unable to build DatabaseInformation at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:89) at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:185) at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:66) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:293) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:143) at java.base/java.util.HashMap.forEach(HashMap.java:1421) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:140) at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:336) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:415) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1425) . 4 more Caused by: org.postgresql.util.PSQLException: Колонки start_value не найдено в этом ResultSet’’е. at org.postgresql.jdbc.PgResultSet.findColumn(PgResultSet.java:2939) at org.postgresql.jdbc.PgResultSet.getLong(PgResultSet.java:2822) at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.resultSetStartValueSize(SequenceInformationExtractorLegacyImpl.java:110) at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.lambda$extractMetadata$0(SequenceInformationExtractorLegacyImpl.java:54) at org.hibernate.tool.schema.extract.spi.ExtractionContext.getQueryResults(ExtractionContext.java:50) at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:39) at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:66) at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.(DatabaseInformationImpl.java:60) at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:176) . 12 more Process finished with exit code 1 

Вроде же всё делал по Getting Started Guide и User Guide.

Hibernate

Hibernate is an object-relational mapping framework that implements the Jakarta Persistence (JPA) specification.

IntelliJ IDEA provides the following:

  • Coding assistance specific to Hibernate.
  • A dedicated facet for managing the Hibernate configuration hibernate.cfg.xml .
  • Additions to the Persistence tool window for managing your Hibernate items, creating configuration files and persistent classes, navigating to related source code in the editor, opening diagrams and consoles, and more.
  • Entity-relationship (ER) diagrams that you can access from the Persistence tool window.
  • An ability to generate managed entity classes and object-relational mappings for them by importing a database schema or an EJB deployment descriptor file ejb-jar.xml .
  • The Hibernate console for writing and running HQL queries, and analyzing the query results.

Create a new Java Enterprise project with Hibernate

  1. Click New Project on the Welcome screen or select File | New | Project .
  2. From the Generators list, select Jakarta EE .
  3. Name the new project, select a build tool, a language you want to use, and select the Web application project template.
  4. From the JDK list, select the JDK that you want to use in your project. If the JDK is installed on your computer, but not defined in the IDE, select Add JDK and specify the path to the JDK home directory. If you don’t have the necessary JDK on your computer, select Download JDK . Creating new project with Hibernate support
  5. On the next step of the wizard, select the Java Enterprise version to be supported.
  6. From the Dependencies list, select the Persistence (JPA) specification and Hibernate as the implementation. New Java Enterprise project with JPA and Hibernate
  7. Click Create .

For more information about creating a Java Enterprise project, refer to Tutorial: Your first Java EE application.

IntelliJ IDEA creates the default project structure with the JPA facet and all the necessary libraries as external dependencies, such as javax.persistence for the JPA specification and org.hibernate for the Hibernate framework. If you specified an application server, IntelliJ IDEA will also create a run configuration to start the server, build and deploy the artifact.

Enable Hibernate support for an existing project

  1. Open the build file in the editor ( pom.xml or build.gradle depending on the build tool that you use in your project).
  2. Add the following dependency, but make sure to change the version according to your project’s requirements:

Пример Hibernate

Рассмотрим разработку Hibernate примера в среде Eclipse. Основная цель, которую будем преследовать в данном Hibernate примере — показать технологию использования библиотеки по записи объектов в таблицу БД, чтению объектов таблицы, поиску объекта по идентификатору записи ID.

На следующем скриншоте представлена структура проекта HibernateExample в среде разработки IDE Eclipse.

Hibernate пример включает :

  • класс тестирования PersonTest.java;
  • объект/класс Person.java;
  • файл описания (mapping) класса person.hbm.xml
  • файл конфигурации hibernate.cfg.xml, включающий описание подключения к серверу БД;
  • библиотеки директории lib.

В качестве СУБД в примере будем использовать MySQL. В БД создадим таблицу «test.person» в схеме «test». Конечно, таблицу можно было бы также создать с использованием Hibernate, но в данном примере мы это не будем рассматривать.

Исходный код примера можно скачать здесь.

Описание таблицы базы данных
CREATE TABLE test.person ( id INT (11) NOT NULL, name VARCHAR (128) NOT NULL, PRIMARY KEY (id) ) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_general_ci;

Тестовая таблица «person» будет включать два поля : идентификатор записи «id» и имя «name». Записи в таблице будут храниться в кодировке «UTF8».

Исходный код объекта/класса

Создадим класс Person с полями id — идентификатор записи и name — имя. Класс, с которым работает Hibernate, называется сущностью Entity. Для того, чтобы класс Person стал сущностью, добавим аннотацию @Entity. Сущности типа Person будут храниться в таблице, имя которой совпадает с именем класса, т.е. «person». Значения полей сущностей будут храниться в одноименных колонках этой же таблицы. Сущность должна иметь «persistence identity», или идентификатор. Это — ключ, который однозначно её идентифицирует и выделяет среди других сущностей такого же типа. Идентификатор указывается с помощью аннотации @Id. В классе «Person» в качестве идентификатора можно использовать поле id, которое соответствует колонке первичного ключа в таблице «test.person».

import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Person < @Id int id; String name; public Person() <>public Person(int id, String name) < super(); this.id = id; this.name = name; >public int getId() < return id; >public void setId(int id) < this.id = id; >public String getName() < return name; >public void setName(String name) < this.name = name; >public String toString() < return "Person "; > >
Конфигурационный файл объекта
Конфигурационный файл hibernate.cfg.xml

Конфигурационный XML-файл hibernate.cfg.xml определяет параметры СУБД, учетную запись (login, password) подключения к серверу БД, а также дополнительные параметры, которые используются при работе с сервером.

     com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/test root password 1 true org.hibernate.dialect.MySQLDialect thread utf8 utf8 true   

В файле конфигурации hibernate.cfg.xml определена база данных MySQL, пул подключений — 1 соединение. В свойстве «show_sql» устанавливаем истиное значение, чтобы в консоли были отображены генерируемые библиотекой Hibernate SQL-скрипты. Дополнительно устанавливаем кодировку записей UTF8, чтобы можно было бы работать с кириллицей.

Тестирование Hibernate примера

Создадим класс «PersonTest» для проверки работы библиотеки. В методе main() вызывается конструктор класса, в котором вызывается метод createHibernateSession() для создания сессии Session. Если сессия создана успешно, то в методе recordsAdd() в таблицу БД добавляются два объекта. Подробно о состоянии сущности, сессии Session, ее методах перевода сущности из одного состояния в другое, представлено здесь.

После создания сессии в методе recordsRead() объекты из БД «загружаются» в коллекцию и отображаются в консоли. В заключении программа вызывает метод recordFind(final int id) для поиска в таблице БД объекта по идентификатору записи и завершает работу — закрывает сессию.

import java.util.List; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import net.common.model.Person; public class PersonTest < private Session session = null; private final String[][] persons = , >; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Процедура создания сессии * @return org.hibernate.Session */ private Session createHibernateSession() < SessionFactory sessionFactory = null; ServiceRegistry serviceRegistry = null; try < try < Configuration cfg = new Configuration(). addResource("person.hbm.xml").configure(); serviceRegistry = new StandardServiceRegistryBuilder(). applySettings(cfg.getProperties()).build(); sessionFactory = cfg.buildSessionFactory(serviceRegistry); >catch (Throwable e) < System.err.println("Failed to create sessionFactory object." + e); throw new ExceptionInInitializerError(e); >session = sessionFactory.openSession(); System.out.println("Создание сессии"); > catch (Exception e) < System.out.println(e.getMessage()); >return session; > //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Процедура добавления записей в таблицу */ private void recordsAdd() < try < System.out.println("Добавление записи в таблицу БД"); Transaction tx = session.beginTransaction(); for (int i = 0; i < persons.length; i++) < Person person = new Person(); person.setId(Integer.valueOf(persons[i][0])); person.setName(persons[i][1]); session.save(person); >tx.commit(); System.out.println("\tЗаписи добавлены"); > catch (Exception e) < System.out.println(e.getMessage()); >> //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Процедура чтения записей */ private void recordsRead() < System.out.println("\nЧтение записей таблицы"); String query = "select p from " + Person.class.getSimpleName() + " p"; @SuppressWarnings("unchecked") Listlist = (List)session.createQuery(query).list(); System.out.println(list); > //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Процедура поиска записи */ private void recordFind(final int id) < System.out.println("\nЧтение записи таблицы по ID"); Person person = (Person) session.load(Person.class, id); System.out.println(person); >//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Конструктор класса */ public PersonTest() < // Создание сессии session = createHibernateSession(); if (session != null) < // Добавление записей в таблицу recordsAdd(); // Чтение записей таблицы recordsRead(); // Поиск записи по идентификатору recordFind(Integer.valueOf(persons[1][0])); // Закрытие сессии if (session.isOpen()) session.close(); >> //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public static void main(String[] args) < new PersonTest(); System.exit(0); >>

Для того, чтобы действия над сущностями сохранялись в базе данных, методы для создания, изменения и удаления сущностей должны вызываться в транзакциях. Для открытия и закрытия транзакций используются методы beginTransaction() и commit() объекта Transaction

Следует обратить внимание на то, как объект сохраняется в таблице БД, как читается список объектов и как выполняется поиск объекта по идентификатору.

// сохранение объекта в таблице : recordsAdd() session.save(person); // чтение списка объектов : recordsRead List list = (List)session.createQuery(query).list(); // чтение объекта по идентификатору : recordFind Person person = (Person) session.load(Person.class, id);

В консоли будут отражены следующие результаты работы приложения :

Создание сессии Добавление записи в таблицу БД Hibernate: insert into person (Name, id) values (?, ?) Hibernate: insert into person (Name, id) values (?, ?) Записи добавлены Чтение записей таблицы Hibernate: select person0_.id as id1_0_, person0_.Name as Name2_0_ from person person0_ [Person , Person ] Чтение записи таблицы по ID Person

Автоматически генерируемые библиотекой SQL-скрипты отображены в консоли после ключевого слова «Hibernate». Чтобы блокировать «вывод» SQL-скриптов необходимо свойству «show_sql» в файле конфигурации присвоить значение false.

Пример использования генератора последовательностей Sequence в Hibernate можно увидеть здесь.

Описание аннотаций связей между сущностями с примерами представлено здесь.

Ваше первое приложение на Hibernate

Java-университет

Ваше первое приложение на Hibernate - 1

В этой статье вы познакомитесь с одним из наиболее популярных enterprise-фреймворков для Java и создадите свое первое приложение на Hibernate. Никогда не слышали о Hibernate? Может быть, слышали о нем, но не пользовались? Или пытались начать, но не получилось? Во всех трех случаях — добро пожаловать под кат:) Всем привет! В этой статье я расскажу об основных особенностях фреймворка Hibernate и помогу вам написать свое первое мини-приложение. Для этого нам понадобятся:

  1. Intellij Idea Ultimate Edition;
    Качаем с официального сайта и активируем 30-дневную пробную версию.
  2. PostgeSQL — одна из самых популярных современных систем управления базами данных (СУБД);
  3. Maven (уже зашит в IDEA);
  4. Немного терпения.

Статья ориентирована прежде всего на тех, кто никогда не работал с данной технологией, поэтому количество кода было максимально уменьшено. Приступим!

Что такое Hibernate?

Это — одна из наиболее популярных реализаций ORM-модели. Объектно-реляционная модель описывает отношения между программными объектами и записями в БД. Конечно, функционал Hibernate очень широк, но мы остановимся на самых простых функциях. Наша цель: создать CRUD-приложение (Create,Read,Update,Delete), которое будет уметь:

  1. Создавать пользователей (User), а также искать их в базе данных по ID, обновлять их данные в базе, а также удалять из базы.
  2. Присваивать пользователям объекты автомобилей (Auto). Создавать, редактировать, находить и удалять автомобили из базы данных.
  3. Кроме того, приложение должно автоматически удалять «бесхозные» автомобили из БД. Т.е. при удалении пользователя, все принадлежащии ему автомобили также должны быть удалены из БД.

Структура нашего проекта будет следующей: Ваше первое приложение на Hibernate - 2Как видите, ничего сложного. 6 классов + 1 файл с конфигами. Для начала, создадим новый maven-проект в Intellij Idea. File -> New Project. Из предлагаемых типов проектов выбирайте Maven и переходите дальше.Ваше первое приложение на Hibernate - 3Apache Maven — фреймворк для автоматизации сборки проектов на основе описания их структуры в файлах на языке POM. Вся структура вашего проекта будет описана в файле pom.xml, который IDEA сама создаст в корне вашего проекта. В настройках проекта вам нужно будет указать параметры Maven — groupId и artifactId. Обычно в проектах groupId наименование организации или подразделения, туда записывают доменное имя организации или сайта проекта. В свою очередь artifactId — название проекта. Для groupdId можете указать com.вашНикнейм.javarush , на работу приложения это никак не повлияет. Для artifactId выберите любое понравившееся вам название проекта. Version тоже можете оставить без изменений.Ваше первое приложение на Hibernate - 4На последнем экране просто подтвердите ранее введенные данные.Ваше первое приложение на Hibernate - 5Итак, проект мы создали, осталось всего ничего — написать код и заставить его работать 🙂 Прежде всего, если мы хотим создать приложение, работающие с базой данных — нам определенно не обойтись без базы данных! Качаем PostgreSQL отсюда (я использую 9 версию). В PostgreSQL имеется созданный по умолчанию пользователь ‘postgres’, пароль для него вам нужно будет придумать при установке. Не забывайте пароль, он нам понадобится позже! (Вообще, пользоваться дефолтной БД в приложениях — bad practice, но с целью сократить объем геморроя с созданием своей БД обойдемся ей). Если вы не дружите с командной строкой и SQL-запросами — есть хорошая новость. Intellij IDEA предоставляет вполне годный пользовательский интерфейс для работы с БД. Выглядит он так:Ваше первое приложение на Hibernate - 6(находится на правой боковой панели IDEA, вкладка Database) Для создания поключения нажмите «+», выберите нашего провайдера (PostgeSQL). Заполните поля с пользователем, именем БД (и то и другое — postgres) и введите пароль, который задали при установке PostgreSQL. При необходимости — скачайте драйвер Postgres, это можно сделать на этой же странице. Намжмите «Test Connection», чтобы проверить, что соединение с БД установлено. Если видите надпись «Successful» — едем дальше. Теперь создадим нужные нам таблицы. Всего их будет две — users и autos. Параметры для таблицы users: Ваше первое приложение на Hibernate - 7Обратите внимание на то, что id является первичным ключом (Primary Key). Если не знаете что такое первичный ключ в SQL — гугл, это важно. Настройка для таблицы autos: Ваше первое приложение на Hibernate - 8Для autos нужно настроить Foreign Key — внешний ключ. Он будет связывать наши таблицы. Советую почитать про него подробнее; если говорить совсем просто — он ссылается на внешнюю таблицу, в нашем случае на users. Если машина принадлежит юзеру с то в поле user_id таблицы autos у нее будет 1. Так мы в нашем приложении связываем пользователей с их автомобилями. В нашей таблице autos роль внешнего ключа будет выполнять поле user_id. Оно будет ссылаться на поле id таблицы users. Ваше первое приложение на Hibernate - 9Таким образом, мы создали базу данных с двумя таблицами. Осталось понять, как управлять ей из Java-кода. Начнем мы с файла pom.xml, в котором нам необходимо подключить нужные библиотеки (на языке Maven они называются dependencies — «зависимости»). Все библиотеки хранятся в центральном репозитории Maven. Те из них, которые вы укажете в pom.xml, вы сможете использовать в проекте. Ваш pom.xml должен выглядеть так: Ваше первое приложение на Hibernate - 10Ничего сложного, как видите. Мы добавили всего 2 зависимости — для использования PostgreSQL и Hibernate.

Теперь перейдем к Java-коду. Создайте все необходимые пакеты и классы проекта. Для начала, нам понадобятся модели данных — классы 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 Listautos; 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 getAutos() < return autos; >public void setAutos(List autos) < this.autos = autos; >@Override public String toString() < return "models.User 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; >> 
  • Должен иметь пустой конструктор ( public или protected );
  • Не может быть вложенным, интерфейсом или enum ;
  • Не может быть final и не может содержать final -полей/свойств;
  • Должен содержать хотя бы одно @Id-поле.
  • Содержать непустые конструкторы;
  • Наследоваться и быть наследованным;
  • Содержать другие методы и реализовывать интерфейсы.
 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; > > 

Ваше первое приложение на Hibernate - 11

В этом классе мы создаем новый объект конфигураций 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 findAll() < Listusers = (List) 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 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); >> 

Ваше первое приложение на Hibernate - 13

Как видите, в таблице 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); >> 

Ваше первое приложение на Hibernate - 15

Работает! А что если удалить пользователя? Очистим таблицу 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», обзор на которую я делал в одной из прошлых статей. Надеюсь, эта статья была полезна читателям. Если у вас будут вопросы — задавайте их в комментариях, с радостью отвечу 🙂 Также не забывайте поддержать автора в конкурсе, поставив «Нравится». А лучше — «Очень нравится» 🙂 Успехов в учебе!

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

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