Hibernate — быстрый старт. Пример приложения Hibernate 5 Hello World

Java Hibernate — настройка, подключение к БД и создание простого приложения

Hibernate — один из самых популярных фреймворков для Java, выполняющая объектно-реляционное отображение (object-relational mapping — ORM). Этот фреймворк значительно сокращает время на реализацию задач отображения данных из таблиц в классы (POJO).

Используемые технологии:

Hibernate 5.0.1.Final

Maven 3.2.5

IntelliJ IDEA 14

MySQL 5.6.25

1. Описание задачи

Необходимо создать пустой проект maven, подключить к нему фреймворк Hibernate. Затем подключиться к базе данных и записать в таблицу данные.

2. Структура проекта

Hibernate Structure

Здесь созданы сущности из БД, файл для создания sessionFactory и файл настроек hibernate.cfg.xml.

3. Создание проекта

Создаем простой maven проект. Дальше подгрузим всё через pom.xml

hibernate maven start

4. pom.xml

На самом деле для простейшего приложения нам бы понадобились всего две зависимости: mysql-connector-java и hibernate-core. Но т.к. остальные всё равно вам скорее всего понадобятся, то для удобства поиска в следующий раз я собрал всё в одном файле. Также обратите внимание, что при использовании hibernate-entitymanager подгружать hibernate-core и другие зависимости не нужно — всё будет найдено автоматически. Правда существуют рекомендации всё же подключать зависимости по отдельности во избежание глюков и лишней работы по отлавливанию исключения.

5. Подключение фреймворка Hibernate в проект

hibernate maven addFramework

В Idea нажимаем на проект, дальше Add Framework Support… и там выбираем Hibernate. Если у вас подгрузились зависимости, указанные выше, то будет доступен выбор из зависимостей maven. Так же можно установить галочку Import database schema о настройке схемы базы данных (БД) сразу после нажатия на ок. Я покажу эту настройку отдельно.

6. Создание файла настроек фрейморка hibernate.cfg.xml

Теперь нам нужно создать главный файл настроек Hibernate. Сделать это можно несколькими способами, вот один из них:

add hibernate.cfg.xml

В настройках проекта (ctrl+alt+shift+s) выбираем хибернейт и дальше справа +. Указываем путь где будет храниться этот файл и жмем ок.

Листинг уже с настройками показан ниже. Обратите внимание, что после автоматической генерации сущностей свойства имя пользователя и пароль перезаписываются (или вообще удаляются). Так что здесь приведен уже конечный файл:

7. Подключение к базе данных MySQL

Этот пункт не будет рассмотрен в этой статье, т.к. он подробно рассматривается в отдельной заметке. Здесь можно посмотреть как создать базу данных MySQL и подключиться к ней в Idea.

8. Создание сущностей (POJO-классы) для колонок из базы данных

После того как мы подключились к БД можно сгенерировать сущности автоматически. Для этого в IDEA можно выбрать пункт Generate Persistence Mapping — By Database Schema.

Generate Persistance

Далее появится такое окошко. Прописываем схему базы данных, куда будут складываться классы, а также префикс и суффикс к сгенерированным названиям. В моем случае я выбрал суффикс Entity и поэтому колонка contact будет замапина в класс ContactEntity.

Import Database Schema

Выбираем какие настройки будут сгенерированы и жмем ок. Хоть на скриншоте и выбраны все галочки, но в итоге я удалил xml, которые были сгенерированы (Generate Separate XML per Entity — для каждой сущности будут сгенерирован свой xml файл) и оставил только классы с аннотациями (наиболее удобный и распространенный вариант, хотя вариант с xml имеет свои достоинства)

Результат:

Generated Entities

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

Всё генерится замечательно, но есть некоторые особенности, которые обязательно необходимо учитывать. В этом примере сразу всплывают несколько вещей, которые я вам хотел показать в качестве примера. Итак.

В таблицах используется колонка с датой.
Ее формат SQL Date. Именно так и сгенерится класс ContactEntity. Но в Java используется java.util.Date и это нужно учитывать. Для того, чтобы связать дату из sql.Date и java.util.Date необходимо заменить аннотацию @Basic на @Temporal, а так же изменить тип возвращаемого результата (после автоматической генерации был sql.Date)

В таблице при создании была создана колонка для контроля версий. Это тоже было пропущено при создании сущностей. Для исправления применяем аннотацию @Version:

Третий момент в этом примере связан с связью таблиц между собой. Этот вопрос будет рассмотрен в других статьях, но чтобы вы смогли запустить этот пример нужно исправить в этом методе два параметра на false, вместо true из класса ContactHobbyDetailEntityPK:

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

В примере будет использована только одна сущность и ниже приведён её листинг:

10. Реализация org.hibernate.SessionFactory

Для работы с hibernate используется реализация интерфейса SessionFactory. Отметьте себе, что она создается один раз для приложения!

Есть несколько примеров как создается реализация sessionFactory. Здесь показана реализация из официального мануала jboss.org, с добавлением геттера и метода по завершению подключения:

11. Запуск приложения

Для запуска напишем простенький класс и запишем одну строку в таблицу:

После запуска проверим что получилось прямо из среды разработки. Как видим одна строчка записалась успешно:

first run result

 

 

Ссылки для скачивания

Hibernate Hello World

Share Button
32
65757 Total Views 1 Views Today

42 thoughts on “Hibernate — быстрый старт. Пример приложения Hibernate 5 Hello World

  1. Михаил:

    Добрый день!
    Спасибо за статью, заработало почти с первого раза!
    Когда вставляю ваш код из class HibernateSessionFactory, то программа падает.
    Как все таки удобно работать в Idea

    1. Nick V.:

      Расскажите, пожалуйста, в чем ошибка и как решили. Это поможет другим читателям (или я подправлю код в исходниках, если дело в них).
      P.S. скачал исходники в конце статьи и запустил как есть, всё отработало.

    2. Юрий:

      Очень интересно узнать как поправили HibernateSessionFactory. Бросает «Could not locate cfg.xml resource [hibernate.cfg.xml] «

      1. Nick V.:

        Скорее всего у вас идет неправильная ссылка на местонахождение файла настроек. Часто бывает что cfg лежит в папке webapp/resources, а не src/resources. В любом случае посмотрите как обращаетесь к файлу и как прописаны настройки.

  2. Igor:

    Exception in thread «main» org.hibernate.exception.SQLGrammarException: could not execute statement

    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table ‘javastudy.Contact’ doesn’t exist

    🙁

  3. Alex:

    Добрый день

    делал по вашему примеру и когда сделал 8 пункт выскочила ошибка

    Connection to hibernate.cfg.xml/Hibernate failed
    Could not create connection to database server. Attempted reconnect 3 times. Giving up.

    Из этого я понял что Hibernate не может соединится с базой данных. В чем может быть причина?

     

    1. Alex:

      В итоге я сделал до конца приложение. В базу данные добавляются. Но вот что странное. На вкладке DataBase появилось два типа подключения к базе. Одно через MySQL и другое через Hibernate. Через MySQL все работает. Я могу посмотреть что элементы в таблицы добавляются. А вот когда пробую сделать тоже самое через Hibernate, то не получается. Вот скриншот.

       

        1. На скрине просто две разных базы. Судя по описанию выше — приложение не видит настройки соединения или они не правильные. Вам нужно смотреть под вашу локальную базу что и как. А красное поле с ошибкой указывает на неправильную авторизацию.

  4. Сергей:

    Получил Exception на выходе (

    Что может быть не так?

    Exception in thread «main» java.lang.ExceptionInInitializerError: Initial SessionFactory failedorg.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
    at utils.HibernateSessionFactory.buildSessionFactory(HibernateSessionFactory.java:25)
    at utils.HibernateSessionFactory.<clinit>(HibernateSessionFactory.java:10)
    at main.AppMain.main(AppMain.java:11)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

    1. Сергей:

      Ошибка происходит в этом блоке:

      1. Виктор:

        Сергей, а как Вы решили проблему?
        У меня такая же ошибка.

    2. Сергей:

      Отбой, с Вашим проектом все заработало.

      Появился еще вопрос: почему в моих POJO классах после их сборки прописалось?

      У Вас же

      1. Честно говоря не вспомню дописывал это специально или это было сгенерировано. В любом случае, думаю, узнать что это за два пункта у вас не составит труда:)

        1. Антон:

          Подскажите, в чём может быть проблема: нажимаю на проект, add framework support — вижу только grovee and Kotlin.

          1. IDEA Community Edition? У автора Ultimate и в ней расширенная поддержка фреймворков.

        2. Антон:

          а что же мне делать в таком случае?

          1. Прописать всё руками и добавить зависимости через maven. Или подумать как многие работают с Ultimate IDEA (например можно купить).

        3. Антон:

          Поставил себе Ultimate, почти всё заработало, кроме этого:
          Exception in thread «main» java.lang.ExceptionInInitializerError: Initial SessionFactory failedorg.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
          at HibTestProject.HibernateSessionFactory.buildSessionFactory(HibernateSessionFactory.java:25)
          at HibTestProject.HibernateSessionFactory.<clinit>(HibernateSessionFactory.java:10)
          at HibTestProject.AppMain.main(AppMain.java:11)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
          at java.lang.reflect.Method.invoke(Method.java:497)
          at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

           

          Не пойму, в чём проблема? Подскажите пожалуйста.

          1. Кирилл:

            Антон,

            Я тоже столкнулся с этой проблемой. Есть предположение, что это связанно с версией драйвера для MySQL. Автор использует версию 5.1.34, я же пытался запустить с версией 6.0.3. Попробуйте изменить версию на более старую, для меня это сработало.

      2. Владимир:

        Сергей, по предыдущему пункту с исключениями, в чем была ошибка? Такая же ситуация. Спасибо.

        1. n3sst1:

          Проблема в том, что idea убирает поля
          <property name=«connection.username»>root</property>
                  <property name=«connection.password»>admin</property>

          Проверьте их наличие, в случае отсутствия таковых- добавьте.

  5. noob:

    Совсем не знаю maven потому и вопрос, пакет ru.javastudy.hibernate в ручную создаются? или  maven’ ом  т.к. прописано в pom.xml

    <groupId>ru.javastudy</groupId>
       <artifactId>ru.javastudy.hibernateStart</artifactId>

    ???

    И ещё вопрос как в реальных проектах принято добавлять записи в БД через один объект
    ContactEntity contactEntity = new ContactEntity();

            contactEntity.setBirthDate(new java.util.Date());
            contactEntity.setFirstName(«Nick»);
            contactEntity.setLastName(«VN»);
    и просто переменить аргументы метода с «Nick» и «VN» на допустим свой класс string типа:

      contactEntity.setFirstName(MyStringName);
      contactEntity.setLastName(MyStringLastName);

    или на каждую запись создавать новый
    ContactEntity contactEntity = new ContactEntity();
    ?

    1. в pom.xml прописываются зависимости, которые потом подгрузятся как jar файлы. Пакеты никакие не создаются.

      Как писать в базу зависит от того как хранятся объекты и откуда берутся данные и собственно как происходит запись в БД. В общем плодить любые лишние объекты это расход ресурсов.

      1. noob:

        Ясно, спасибо за быстрый ответ на счёт Maven

        Ну допустим данные берутся  с формочки из полей text тогда   contactEntity должен быть один? и просто его методы подставлять аргументы string и всё?

        кстати что то у меня ошибка:

        SessionFactory failed org.hibernate.MappingException: Repeated column in mapping for entity: org.learning.hibernate.dao.ContactHobbyDetailEntity column: contact_id (should be mapped with insert=»false» update=»false»)

        пытался исправить, что в ошибке требует, не помогло, всё сделал точно так как в туториале тут всё изменил как и написанно:-

        ContactHobbyDetailEntityPK:

        //NOTE that autocreate was insertable = true, updatable = true, but need both false !!!
        @Column(name = «hobby_id», nullable = false, insertable = false, updatable = false, length = 20)
        @Id
        public String getHobbyId() {
        return hobbyId;
        }
        но ошибку то бьёт почему то в классе ContactHobbyDetailEntity не знаете почему?

        1. Например в JSF у вас будет один ContactEntity с set\get методами. И этот один объект будет изменяться и записываться в базу. Для других случаев может создаваться новый объект для новых данных.
          В трейсе ошибки написано что нужно сделать (повторяется колонка и параметры маппинга не те).

          1. noob:

            параметры маппинга были заданны точ в точ как у вас в туториале 3 раза перепроверял, странно, но вот в классе ContactHobbyDetailEntity действительно сгенерилось немного не так:

            @ManyToOne
            @JoinColumn(name = «contact_id«, referencedColumnName = «ID«, nullable = false)
            public ContactEntity getContactByContactId() {
            return contactByContactId;
            }

            а у вас в исходниках:

            @ManyToOne
            @JoinColumn(name = «hobby_id«, referencedColumnName = «hobby_id«, nullable = false)
            public HobbyEntity getHobbyByHobbyId() {
            return hobbyByHobbyId;
            }

            и название класса другое…странно… с чего бы это… ведь и базу с который генерил у вас же взял…

            сменил  на  @JoinColumn(name = «hobby_id, … )  и всё заработало… станно всё это…

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

  6. Veda:

    Здравствуйте!

    Спасибо, очень полезный туториал! Все заработало, пусть не с первого раза, но заработало) =)!

    Тем, кто так и не решил ошибку компиляции даю совет — проверьте настройки hibernate.cfg.xml. Я удалила все xml с настройками для классов, оставила только Entity, то есть только классы. Обнаружила, что у меня не был прописан диалект, логин и пароль. После настройки этого, все заработало.

    Удачи!

  7. Иван:

    Здравствуйте!

    Подскажите, пожалуйста, информацию по автоматическому созданию связей между таблицами.

  8. Дмитрий:

    Здравствуйте!

    Шикарный туториал!!! Огромное человеческое спасибо!

  9. Юрий:

    Огромное Вам спасибо за статью! Но у меня возникла ошибка и не понимаю как её исправить, вроде бы все xml на месте, не могли бы Вы помочь разобраться

     

    авг 20, 2016 4:48:50 PM org.hibernate.Version logVersion
    INFO: HHH000412: Hibernate Core {5.0.1.Final}
    авг 20, 2016 4:48:50 PM org.hibernate.cfg.Environment <clinit>
    INFO: HHH000206: hibernate.properties not found
    авг 20, 2016 4:48:50 PM org.hibernate.cfg.Environment buildBytecodeProvider
    INFO: HHH000021: Bytecode provider name : javassist
    авг 20, 2016 4:48:51 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
    INFO: HCANN000001: Hibernate Commons Annotations {5.0.0.Final}
    Exception in thread «main» java.lang.ExceptionInInitializerError: Initial SessionFactory failedorg.hibernate.boot.MappingNotFoundException: Mapping (RESOURCE) not found : ru/javastudy/hibernate/dao/ContactEntity.hbm.xml : origin(ru/javastudy/hibernate/dao/ContactEntity.hbm.xml)
    at ru.javastudy.hibernate.utils.HibernateSessionFactory.buildSessionFactory(HibernateSessionFactory.java:28)
    at ru.javastudy.hibernate.utils.HibernateSessionFactory.<clinit>(HibernateSessionFactory.java:13)
    at ru.javastudy.hibernate.main.AppMain.main(AppMain.java:15)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

    1. В ошибке сказано не найден маппинг ru/javastudy/hibernate/dao/ContactEntity.hbm.xml. Смотрите куда потеряли (или, скорее всего, его не видит приложение). Кстати вполне гуглится куча ответов по этой ошибке…

  10. Дмитрий:

    Здравствуйте. Такой вопрос: можно ли быстро и безболезненно прикрутить к этому проекту Spring MVC, а также заменить БД на Postgresql, или даже и пытаться не стоит?

    1. Можно и это не очень долго. Можете почитать другие статьи по настройке Spring MVC на этом или других сайтах.

      1. Олег:

        у меня аналогичная ошибка:

        INFO: HHH000369: Error stopping service [class org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl] : java.lang.NullPointerException
        Exception in thread «main» java.lang.ExceptionInInitializerError: Initial SessionFactory failedorg.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
        at ru.javastudy.hibernate.utils.HibernateSessionFactory.buildSessionFactory(HibernateSessionFactory.java:25)
        at ru.javastudy.hibernate.utils.HibernateSessionFactory.<clinit>(HibernateSessionFactory.java:10)
        at ru.javastudy.hibernate.main.AppMain.main(AppMain.java:12)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

        подскажите, пожалуйста, как поправить

        1. Тулеген:

          Вставил в сгенерированный hibernate.cfg.xml вот эти строчки и все завелось:

          <property name=»dialect»>org.hibernate.dialect.MySQLDialect</property>
          <property name=»connection.username»>username</property>
          <property name=»connection.password»>password</property>

  11. Ульяна:

    Подскажите, почему после запуска main, программа не завершается? В таблицу данные добавляются, но процесс выполнения не завершается.. Так надо?

    1. вввв:

      поздно, но возможно кому-то понадобится. Сам промучался не меньше часа в поисках.

      Замените session.close(); на session.getSessionFactory().close();

      и сессия закроется сразу.

  12. Vic:

    Рабочая версия с использование PostgreSQL

    https://github.com/golfstream83/Hibernate_test

    1. Виталий:

      Не указаны последовательности в ваших Entity.

      @SequenceGenerator(…)

      @GeneratorValue(…)

      И автоматическая генерация сущностей не создает это и настроек для этого я не нашел.

      Так что модуль крайне сырой и не учитывает всех тонкостей.

  13. Alena:

    Спасибо, огромное! У меня впервые получилось подключить Hibernate, сколько раз до этого пробовала, ничего не получалось.

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