Топ-100Hibernate CRUD приложение с сервисным уровнем - CodOrbits
LogoCodOrbits

Раздел: Spring MVC CRUD

Изучите реализацию операций CRUD (создание, чтение, обновление, удаление) с использованием Spring MVC и баз данных.

Все разделы
Иконка Spring MVC CRUD

Hibernate CRUD приложение с сервисным уровнем

Last updated: 11 мая 2025 г.

В прошлом уроке мы построили Crud приложение, но это был не совсем правильный способ его построения. В этом уроке мы немного модернизируем наше CRUD приложение.

В прошлом уроке у нас было всего два уровня в нашем приложении, это:

  • Уровень контроллера, который принимает запросы пользователя и в котором должна была находиться вся какая-либо бизнес логика нашего приложения
  • и ДАО уровень, который исключительно для прямого взаимодействия с БД.
Search Icon

Но правильно чтобы бил еще один уровеньсервисный.

Давайте создадим папку service и создадим в ней сервисный класс.

Далее пожробнее зачем он нужен.

В сервис классе внедряются все ДАО, которые есть в приложении. Таким образом объект сервиса объединяет все ДАО объекты и в контроллере можно будет работать с ДАО объектами через единственный объект сервиса.

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

Example

Тогда получается, что:

  • контроллер только получает и отправляет запросы,
  • вся бизнес-логика приложения в сервисе,
  • а в ДАО только чисто код для работы с БД.

То есть, как видим, обеспечиваться дополнительная модульность этой прослойкой.

Также еще очень полезный момент, что обеспечивается слабая связность между дао уровнем и уровнем контроллера.

Помним, что согласно 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
мин.

Similar Articles Icon
Divider

Первое Spring REST API-приложение

22
мин.

Similar Articles Icon
Divider

Создание REST API CRUD приложения

20
мин.

Similar Articles Icon