JavaRush/Курсы/Модуль 4. Работа с БД/Проект по теме: Hibernate #1

Проект по теме: Hibernate #1

Открыта

Помните проект из третьего модуля по фронтенду, где нужно было реализовать админку для rpg для серверного API? Если кто помнит – там на сервере в качестве хранилища использовалась мапа. Естественно, в реальной жизни такие хранилища не используют, а используют базы данных. Целью этого проекта будет написать альтернативную реализацию слоя репозитория с использованием Hibernate.

Для этого нужно:

  1. Сделать fork из репозитория
  2. Скачать свою версию проекта к себе на компьютер.
  3. Добавить зависимости в pom.xml:
    • mysql: mysql-connector-java: 8.0.30
    • org.hibernate: hibernate-core-jakarta: 5.6.11.Final
  4. Сделать maven билд (mvn clean install). Для разнообразия используем Java версии 1.8.
  5. Добавить конфигурацию запуска через Идею. Реализацию этого пункта можно посмотреть в лекции https://javarush.com/quests/lectures/jru.module3.lecture02 (пункт 4). Единственное отличие – другое название артефакта. Если все сделал правильно и запустил приложение – увидишь примерно такую картину:
  6. В Workbench выполнить скрипт создания схемы rpg:
    CREATE SCHEMA `rpg` ;
    
  7. Опционально. Если хочешь посмотреть какое ожидается поведение, можешь в классе com.game.service.PlayerService в параметре конструктора значение аннотации @Qualifier изменить с «db» на «memory». В этом случае Spring будет использовать в качестве реализации интерфейса IPlayerRepository класс PlayerRepositoryMemory. После теста не забудь изменить значение аннотации @Qualifier обратно на «db».
  8. Расставить все необходимые аннотации в ентити-классе com.game.entity.Player. Таблица должна называться «player», схема «rpg». Для енамов используй @Enumerated(EnumType.ORDINAL) кроме аннотации @Column. Напомню, что длина поля name должна быть до 12 символов, поля title – до 30 символов. Абсолютно все поля не должны быть null.
  9. В классе PlayerRepositoryDB добавь private final поле SessionFactory sessionFactory, в конструкторе класса инициализируй это поле. Проперти используй как в обычных задачах (работать будем с БД MySQL версии 8). Из интересного – добавь
    properties.put(Environment.HBM2DDL_AUTO, "update");
    
    Это позволит не создавать таблицу вручную (или через выполнения sql скрипта).
  10. Реализуй все методы класса. Для разнообразия давай поступим так:
    • Метод getAll реализуй через NativeQuery — этот метод должен получать всех игроков  с учетов параметров: pageNumber - номер страницы, pageSize - количество записей на страницу
    • Метод getAllCount реализуй через NamedQuery. Должен возвращать общее количество игроков в базе данных.
    • В методе beforeStop вызови у sessionFactory метод close. За счет наличия аннотации над методом @PreDestroy, Spring вызовет этот метод перед остановкой приложения, и это позволит валидно освободить все ресурсы системы.
    • Реализация остальных методов на твое усмотрение. Но не забывай о транзакциях и коммитах для методов, которые как либо изменяют содержимое БД.
  11. Запусти приложение. Если все сделал правильно – ты получишь рабочее приложение. Вот только данных там никаких нет, так что выполни через Workbench скрипт init.sql (из ресурсов), чтоб они появились. После этого в браузере нажми F5 и проверяй, что все методы ты реализовал правильно.
  12. Было бы интересно посмотреть, какие именно запросы выполняет Hibernate, поэтому добавим логирование запросов. Для этого добавь в pom.xml зависимость p6spy:p6spy:3.9.1. В папке ресурсов создай файл spy.properties, в котором укажи:
    driverlist=com.mysql.cj.jdbc.Driver
    dateformat=yyyy-MM-dd hh:mm:ss a
    appender=com.p6spy.engine.spy.appender.StdoutLogger
    logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat
    
    И в конструкторе класса PlayerRepositoryDB измени две опции:
    properties.put(Environment.DRIVER, "com.p6spy.engine.spy.P6SpyDriver");
    properties.put(Environment.URL, "jdbc:p6spy:mysql://localhost:3306/rpg");
    
    Теперь в выводе сервера по каждому запросу ты будешь видеть 2 строки. Первая – какой стейтмент подготовлен, второй – запрос с вставленными параметрами.

Вот и все, проект готов, поздравляю тебя!

На самом деле, для работы с Hibernate из Spring используется другой подход, о котором мы расскажем в пятом модуле.


Разбор проекта.
Комментарии (11)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Denis Bakhtin
Уровень 100
11 июня, 14:04
Столкнулся с проблемой, не генерируется автоматически таблица Player в схеме rpg. Решение следующее: в качестве диалекта использовать
org.hibernate.dialect.MySQL8Dialect
Юрий Суботинов
Уровень 92
Expert
11 июня 2025, 10:07
У кого не запускается билд и падает с ошибкой из-за отсутствия аннотации @PreDestroy: Проблема кому интересно почитать -> здесь Решение с помощью зависимости: Добавьте зависимость в pom.xml (версию выберите сами, можно последнюю). Обновите файлик pom.xml и замените import в классе PlayerRepositoryDB, а именно: заменить
javax.annotation.PreDestroy;
на
jakarta.annotation.PreDestroy;
Александр
Уровень 115
14 марта 2025, 23:07
Лёгкий приятный проектик. Намного лучше фронтенда в 3 модуле.
Виктор
Уровень 109
18 апреля 2025, 04:22
Да ваще легкотня! Сделал одной левой! Правая была занята...
24 января 2025, 05:22
done 23.01.2025
Mukhan GazirsharifDWH Developer в BCC bank
12 января 2025, 12:26
Hibernate отправлял в БД запрос на создание таблицы, но она упорно не создавалась. Очень долго сидел не находя ошибку. В консоли ошибок не было. Я изначально делал в Community Edition с Smart Tomcat, все работало даже Spring, потом открыл через Ultimate и Local Tomcat но не помогало. Исправил через добавление в pom.xml
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core-jakarta -->
<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-core-jakarta</artifactId>
	<version>5.6.11.Final</version>
</dependency>
Может это из-за того что все поменялось на jakarta.persistence.* или из за того что я не делал "mvn clean install" через терминал, а делал его через саму IDEA через боковую панель. Еще возможно дело было в спринге, я надеялся на него что он сам все сделает.
Мария Ким
Уровень 90
Expert
4 июня 2024, 08:53
да, конечно, ради разнообразия будем использовать java 1.8...Почему бы ради разнообразия не использовать 17 java?
Павел
Уровень 111
Expert
20 декабря 2023, 14:18
После выполнения пункта 9 программа не запускается:
The web application [rpg_hibernate_war_exploded] registered the JDBC driver [com.mysql.cj.jdbc.Driver]
but failed to unregister it when the web application was stopped.
To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Испробовал все найденные варианты решения, ничего не помогло: - редактирования файла Tomcat server.xml - перенос драйверов jdbc в папку сервера - написание класса запуска/остановки драйвера внутри приложения У кого было и как справились?
Данила
Уровень 111
Expert
5 января 2024, 13:20
У меня тоже, но только после 10 ничего не работает
Anonymous #3322801
Уровень 1
Expert
23 ноября 2023, 13:55
И все таки в классе Player надо было делать @GeneratedValue(strategy = GenerationType.IDENTITY) оказывается
Anonymous #3322801
Уровень 1
Expert
21 ноября 2023, 11:17
Из разбора сделала вывод что данные, которые мы вносим самостоятельно hiber не видит, поэтому можно сразу сделать такой код, чтобы добавление в таблицу происходило корректно:
@Id
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "player_seq")
   @SequenceGenerator(name = "player_seq", sequenceName = "player_seq", initialValue = 41, allocationSize=1)
   @Column(nullable = false)
   private Long id;