JPA — пример приложения Hello World. Настройка использования Spring + JPA + Hibernate. Часть 2

Это вторая часть статьи JPA — пример приложения Hello World. Настройка использования Spring + JPA + Hibernate

7. Листинг созданных сущностей

IntelliJ IDEA любезно помогла создать нам сущности в Java классах для каждой из таблиц схемы javastudy:

JPA Database

Если вы до этого не работали с БД и Hibernate (или аналогами), то вас может запутать созданный код. Но на самом деле там всего лишь несколько геттеров\сеттеров для каждой колонки из таблицы, переопределение методов hashCode(), toString() и equals().

Вам же следует обратить внимание только на аннотации @OneToMany (@ManyToOne) и @ManyToMany.

Основная таблица contact:

contact_hobby_detail:

contact_tel_detail:

и последняя hobby:

Не буду вдаваться в подробное описание кода в каждой из сущностей, т.к. оно есть в цикле из Hibernate. В общих словах:

  • таблица contact (сущность ContactEntity) имеет отношение один-ко-многим с таблицей contact_tel_detail. Т.е. у одного контакта может быть несколько телефонов.
    А так же отношение многие-ко-многим с таблицей hobby. Т.е. у одного контакта может ноль и более хобби и одно хобби может быть у нуля или более контактов.
  • над сущностью ContactEntity созданы именованные запросы. Имена говорят сами за себя.

8. Интерфейс и реализация для доступа к данным

Был создан простой интерфейс ContactService:

И его реализация ContactServiceImpl:

Как видите реализованы только три метода, в которых вызываются именованные запросы из класса ContactEntity.

  • @Service — предназначена для идентификации класса как компонента Spring, который предоставляет бизнес-службы другому уровню; этот бин Spring получает имя jpaContactService.
  • @Repository указывает, что класс содержит логику доступа к данным и заставляет Spring транслировать исключения, специфичные для поставщика, в иерархию DataAccessException, определенную Spring. В действительности можно использовать @Repository(«jpaContactService») и избавиться от аннотации @Service; результат будет тем же самым.
  • @Transactional предназначена для определения требований к транзакции.

Отметьте себе как мы получаем доступ к диспетчеру сущностей, интерфейсу EntityManager — с помощью аннотации @PersistenceContext.

9. Запрашивание данных с использованием языка запросов постоянства Java (JPQL)

Чтобы было понятно о каких данных идет речь, приведу скрины схемы:

JPA contact JPA contact_hobby_det

JPA contact_tel_det  JPA hobby

Тест проводится в главном классе с парочкой методов:

Сначала идет загрузка конфигурации спринг. Затем получаем доступ к интерфейсу ContactService. Далее просто вытаскиваем данные и выводим их в консоль.

Замечание
Вначале статьи писал о местонахождении файла spring-context.xml. Пока не перенес его в папку resources, spring отказывался грузить настройки в ctx.load(‘ ‘), даже указывая абсолютный путь C:\…\spring-config.xml. Кстати на stackoverflow написано с точностью до наоборот — не помещать настройки в папку resources. Кто знает в чем разница — можете написать в комментариях.

Результаты вывода:

Для контакта id=3 получили два телефонных номера, 0 хобби.

Для контакта с id=8 получили парочку хобби. И т.д.

Update:

Поменял Long на Integer в методе findById(Integer id), т.к. это соответствует БД:

Сначало создаем запрос TypedQuery<T> query с помощью вызова именованного запроса createNamedQuery(<String name, Class<T> resultClass>). Затем устанавливаем параметр в этом запросе и вызываем одиночный результат.

Результат:

ContactEntity{id=8, Name1 ‘, LastName1’, 2014-09-01, 0}

Частые ошибки

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

Exception in thread «main» org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ru.javastudy.entities.ContactEntity.contactTelDetails

Например такую ошибку можно получить просто обратившись к деталям контакта из метода toString():

Почему и как это исправить описано здесь.

 

Исходные коды

JPA Tutorial — исходные коды

JPA sql helloWorld — дамп базы данных из статьи

Share Button
10
7695 Total Views 3 Views Today

7 thoughts on “JPA — пример приложения Hello World. Настройка использования Spring + JPA + Hibernate. Часть 2

  1. Vladislav:

    В чем отличие между schema и catalog?

  2. Vladislav:

    И еще такой вопрос: сущности, приведенные в этой статье, были сгенерированы полностью автоматически идеей? Или же вручную редактировалось? А то у меня IntelliJ IDEA 2016 какую-то дичь генерирует. Даже связь Many-To-Many не распознает…. Хотя БД та же самая…

  3. Stasyan:

    Очень тяжело читать код, поля в перемешку с getters setters

    1. Stasyan:

      contact_tel_detail: дважды использована сущность ContactEntity с разными переменными

      1. Stasyan:

        если указывать над классом сущности  @Table(name = «hobby», schema = «», catalog = «javastudy») то будет warning в (@Column(name = !!!~~~hobby_id~~~~!!!!, nullable = false, length = 20)

        )от IDEA (Cannot resolve column ‘hobby_id’ less… (Ctrl+F1) This inspection controls whether the Persistence ORM annotations are checked against configured Datasources), по этому желательно писать @Table(name = «hobby», schema = «javastudy», catalog = «»)

      2. Stasyan:

        В статье не прописан листинг класса ContactHobbyDetailEntityPK и важное заполнение аннотации

      3. Stasyan:

        А зачем писать в классе Main  -> «jpaContactService» в ContactService contactService = ctx.getBean(«jpaContactService», ContactService.class);

        Все и без «jpaContactService» работает замечательно

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