Hibernate CRUD приложение с сервисным уровнем
Last updated: 11 мая 2025 г.В прошлом уроке мы построили Crud приложение, но это был не совсем правильный способ его построения. В этом уроке мы немного модернизируем наше CRUD приложение.
В прошлом уроке у нас было всего два уровня в нашем приложении, это:
Уровень контроллера
, который принимает запросы пользователя и в котором должна была находиться вся какая-либо бизнес логика нашего приложения- и
ДАО уровень
, который исключительно для прямого взаимодействия с БД.
Но правильно чтобы бил еще один уровень – сервисный.
Давайте создадим папку service и создадим в ней сервисный класс.

Далее пожробнее зачем он нужен.
В сервис классе внедряются все ДАО, которые есть в приложении. Таким образом объект сервиса объединяет все ДАО объекты и в контроллере можно будет работать с ДАО объектами через единственный объект сервиса.
Также важный момент, что вся бизнес логика приложения больше не будет находиться на уровне контроллера, как в прошлой версии приложения, она теперь будет располагаться на уровне сервиса.
Тогда получается, что:
- контроллер только получает и отправляет запросы,
- вся бизнес-логика приложения в сервисе,
- а в ДАО только чисто код для работы с БД.
То есть, как видим, обеспечиваться дополнительная модульность этой прослойкой.
Также еще очень полезный момент, что обеспечивается слабая связность между дао уровнем и уровнем контроллера.
Помним, что согласно DAO паттерну Dao классы нужны только для сокрытия низкоуровневого взаимодействия с ресурсом, в них не должно быть какой-либо сложной бизнес логики, поэтому если мы внедрим все DAO классы в контроллере и будем использовать их методы в сочетании с бизнес логикой без уровня сервиса, то это может вызвать ряд проблем.
Представим, что в контроллере много где вызывается какой-то метод ДАО класса, например, выборки из таблицы, и мы, например, захотим заменить этот метод на другой метод выборки из другой таблицы, тогда придется везде в контроллере его менять вручную. Здесь как раз и пригодиться сервис метод
в котором код можно менять как нам вздумается в отличии от ДАО метода, где происходит только прямое взаимодействие с какой-либо конкретной таблицей БД.
Теперь пусть на месте ДАО метода, который мы хотим заменить в контроллере будет метод сервис класса и в этом сервис методе пусть вызывается ДАО метод. В этом сервис методе мы можем менять ДАО метод на любой какой нам вздумается. И в этом вся суть, что поменяв единожды ДАО метод в сервис методе он автоматически поменяется везде в контроллере и менять всё вручную в контроллере нам не придется, только ДАО метод в сервис методе.
Это и есть слабая связность между ДАО и контроллером.
Также очевидно, что если мы пишем всю бизнес логику в одном контроллере и если нам придется повторить эту логику в другом контроллере придется копировать ее полностью в него.
Вместо этого лучше написать отдельный метод в сервисе, который будет содержать эту бизнес логику и будет доступен всем контроллерам.
Для начала, создаем интерфейс на основе которого будет создаваться сервис класс:
1package com.MavenWebAps.hibernateCRUDap.service;
2
3import java.util.List;
4
5import com.MavenWebAps.hibernateCRUDap.entity.Actor;
6
7public interface ServiceInterface {
8 public Actor getActor(int actorId);
9 public void setActor(Actor actor);
10 public List<Actor> getListOfActors();
11 public void deleteActor(int actorid);
12}
Давайте же создадим этот сервис класс.
1package com.MavenWebApps.hibernateCRUDap.service;
2
3import java.util.List;
4
5//Также как и @Controller и @Repositiry аннотация
6//@Service наследуется от @Component поэтому
7//спринг анализирует этот класс как особый бин.
8@Service
9//Объект (бин) этого класса-сервиса будет внедрен
10//в контроллере и через этот объект будем работать
11//с ДАО объектами.
12public class ServiceInterfaceImpl implements ServiceInterface {
13
14 //внедряеться ДАО класса Актера.
15 @Autowired
16 private ActorDAO actorDAO;
17
18 //На уровне ДАО убираем @Transactional
19 //на уровне сервиса добавляем @Transactional.
20 @Transactional
21 //Метод для выборки актера из базы.
22 public Actor getActor(int actorId) {
23 //Здесь просто вызываем соответствующий
24 //метод ДАО объекта.
25 return actorDAO.getActor(actorId);
26 }
27
28 @Transactional
29 //Метод для вставки актера в базу.
30 public void setActor(Actor actor) {
31 //Пример слабой связности о которой
32 //говорилось ранее: допустим
33 //в контроллере много где вызываеться
34 //метод setActor этого сервис класса.
35 //Если мы поменяем дао метод setActor
36 //в этом методе на другой дао метод
37 //то он автоматически меняеться везде
38 //в контроллере где вызываеться setActor
39 //сервис класса и в контроллере в каждом
40 //месте использования метода setActor
41 //сервис класса ничего менять не нужно
42 //как если бы там вызывался
43 //setActor ДАО класса.
44 actorDAO.setActor(actor);
45 }
46
47 //Дальше также в сервисных методах вызываються
48 //соответствующие методы ДАО класса. Как видим
49 //здесь простой случай, поскольку приложение
50 //у нас простое и из-за этого особой бизнес
51 //логики у нас нет, потому просто вызываем
52 //Дао методы в сервис методах.
53 @Transactional
54 public List<Actor> getListOfActors() {
55 return actorDAO.getListOfActors();
56 }
57
58 @Transactional
59 public void deleteActor(int actorid) {
60 actorDAO.deleteActor(actorid);
61 }
62}
Поправим контроллер. Уберем из него все ДАО методы и вместо них пусть будут сервис методы.
1package com.MavenWebAps.hibernateCRUDap.controller;
2
3import org.springframework.beans.factory.annotation.Autowired;
4import org.springframework.stereotype.Controller;
5import org.springframework.web.bind.annotation.ModelAttribute;
6import org.springframework.web.bind.annotation.RequestMapping;
7import org.springframework.web.bind.annotation.RequestParam;
8
9import com.MavenWebAps.hibernateCRUDap.entity.Actor;
10import com.MavenWebAps.hibernateCRUDap.service.ServiceInterface;
11
12import org.springframework.ui.Model;
13
14
15@Controller
16@RequestMapping("/actor")
17public class CRUDController {
18
19 //Теперь вместо DAO объекта внедряем сервис
20 //объект (бин) уже через методы которого
21 //будет происходить работа с DAO объектом
22 //для взаимодействия с БД.
23 @Autowired
24 private ServiceInterface sertviceObj;
25
26
27 @RequestMapping("/getListOfActors")
28 public String getListOfActors(Model model) {
29 model.addAttribute("listofactors",
30 //теперь используем sertviceObj
31 sertviceObj.getListOfActors());
32 return "ListOfActorsJSP";
33 }
34
35 @RequestMapping("/showFormForUpdating")
36 public String updateActorsFor(
37 @RequestParam("actorId") int actorid,
38 Model model) {
39 model.addAttribute("someactor",
40 //теперь используем sertviceObj
41 sertviceObj.getActor(actorid));;
42 return "ActorJSPUpdateForm";
43 }
44
45 @RequestMapping("/showFormForSetting")
46 public String setActor(Model model) {
47 model.addAttribute("someactor",
48 new Actor());
49 return "ActorJSPNewActorForm";
50 }
51
52 @RequestMapping("/setActor")
53 public String setActor(@ModelAttribute("someactor") Actor actor, Model model){
54 //теперь используем sertviceObj
55 sertviceObj.setActor(actor);;
56 return "redirect:/actor/getListOfActors";
57 }
58
59 @RequestMapping("/deleteActor")
60 public String deleteActor(
61 @RequestParam("actorId") int actorid,
62 Model model) {
63 //теперь используем sertviceObj
64 sertviceObj.deleteActor(actorid);;
65 return "redirect:/actor/getListOfActors";
66 }
67
68}
Также не забываем убрать Transactional в ДАО классе. Эти аннотации теперь в сервис классе.
1package com.MavenWebAps.hibernateCRUDap.dao;
2
3import java.util.List;
4import javax.transaction.Transactional;
5
6import org.hibernate.Session;
7import org.hibernate.SessionFactory;
8import org.springframework.beans.factory.annotation.Autowired;
9import org.springframework.stereotype.Repository;
10
11import com.MavenWebAps.hibernateCRUDap.entity.Actor;
12
13@Repository
14public class ActorDAOImpl implements ActorDAO {
15
16 @Autowired
17 private SessionFactory sessionFactory;
18
19 //@Transactional
20 public Actor getActor(int actorId) {
21 Session session = sessionFactory.getCurrentSession();
22 return session.get(Actor.class, actorId);
23 }
24
25 //@Transactional
26 public void setActor(Actor actor) {
27 Session session = sessionFactory.getCurrentSession();
28 session.saveOrUpdate(actor);
29 }
30
31 //@Transactional
32 public List<Actor> getListOfActors() {
33 Session session = sessionFactory.getCurrentSession();
34 return session.createQuery("from Actor", Actor.class).getResultList();
35 }
36
37 //@Transactional
38 public void deleteActor(int actorid) {
39 Session session = sessionFactory.getCurrentSession();
40 session.createQuery(
41 "delete from Actor where id=:actorid")
42 .setParameter("actorid", actorid).executeUpdate();
43 }
44
45}
Давайте же перейдем на главную страницу со списком актеров. Как мы помним, на эту страницу можно перейти через обработчик getListOfActors
. Сделаем это:

Как видим, страница успешно открылась. Работает здесь всё аналогично предыдущему уроку, только теперь с сервисным уровнем.
Следующие уроки
Что такое REST API?
21
мин.
Первое Spring REST API-приложение
22
мин.
Создание REST API CRUD приложения
20
мин.