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

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

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

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

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

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

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

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

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

Example

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

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

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

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

Помним, что согласно DAO паттерну Dao классы нужны только для сокрытия низкоуровневого взаимодействия с ресурсом, в них не должно быть какой-либо сложной бизнес логики, поэтому если мы внедрим все DAO классы в контроллере и будем использовать их методы в сочетании с бизнес логикой без уровня сервиса, то это может вызвать ряд проблем.

Представим, что в контроллере много где вызывается какой-то метод ДАО класса, например, выборки из таблицы, и мы, например, захотим заменить этот метод на другой метод выборки из другой таблицы, тогда придется везде в контроллере его менять вручную. Здесь как раз и пригодиться сервис метод в котором код можно менять как нам вздумается в отличии от ДАО метода, где происходит только прямое взаимодействие с какой-либо конкретной таблицей БД.

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

Это и есть слабая связность между ДАО и контроллером.

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

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

Для начала, создаем интерфейс на основе которого будет создаваться сервис класс:

package com.MavenWebAps.hibernateCRUDap.service; import java.util.List; import com.MavenWebAps.hibernateCRUDap.entity.Actor; public interface ServiceInterface { public Actor getActor(int actorId); public void setActor(Actor actor); public List getListOfActors(); public void deleteActor(int actorid); }

Давайте же создадим этот сервис класс.

package com.MavenWebApps.hibernateCRUDap.service; import java.util.List; //Также как и @Controller и @Repositiry аннотация //@Service наследуется от @Component поэтому //спринг анализирует этот класс как особый бин. @Service //Объект (бин) этого класса-сервиса будет внедрен //в контроллере и через этот объект будем работать //с ДАО объектами. public class ServiceInterfaceImpl implements ServiceInterface { //внедряеться ДАО класса Актера. @Autowired private ActorDAO actorDAO; //На уровне ДАО убираем @Transactional //на уровне сервиса добавляем @Transactional. @Transactional //Метод для выборки актера из базы. public Actor getActor(int actorId) { //Здесь просто вызываем соответствующий //метод ДАО объекта. return actorDAO.getActor(actorId); } @Transactional //Метод для вставки актера в базу. public void setActor(Actor actor) { //Пример слабой связности о которой //говорилось ранее: допустим //в контроллере много где вызываеться //метод setActor этого сервис класса. //Если мы поменяем дао метод setActor //в этом методе на другой дао метод //то он автоматически меняеться везде //в контроллере где вызываеться setActor //сервис класса и в контроллере в каждом //месте использования метода setActor //сервис класса ничего менять не нужно //как если бы там вызывался //setActor ДАО класса. actorDAO.setActor(actor); } //Дальше также в сервисных методах вызываються //соответствующие методы ДАО класса. Как видим //здесь простой случай, поскольку приложение //у нас простое и из-за этого особой бизнес //логики у нас нет, потому просто вызываем //Дао методы в сервис методах. @Transactional public List getListOfActors() { return actorDAO.getListOfActors(); } @Transactional public void deleteActor(int actorid) { actorDAO.deleteActor(actorid); } }

Поправим контроллер. Уберем из него все ДАО методы и вместо них пусть будут сервис методы.

package com.MavenWebAps.hibernateCRUDap.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import com.MavenWebAps.hibernateCRUDap.entity.Actor; import com.MavenWebAps.hibernateCRUDap.service.ServiceInterface; import org.springframework.ui.Model; @Controller @RequestMapping(“/actor”) public class CRUDController { //Теперь вместо DAO объекта внедряем сервис //объект (бин) уже через методы которого //будет происходить работа с DAO объектом //для взаимодействия с БД. @Autowired private ServiceInterface sertviceObj; @RequestMapping(“/getListOfActors”) public String getListOfActors(Model model) { model.addAttribute(“listofactors”, //теперь используем sertviceObj sertviceObj.getListOfActors()); return “ListOfActorsJSP”; } @RequestMapping(“/showFormForUpdating”) public String updateActorsFor( @RequestParam(“actorId”) int actorid, Model model) { model.addAttribute(“someactor”, //теперь используем sertviceObj sertviceObj.getActor(actorid));; return “ActorJSPUpdateForm”; } @RequestMapping(“/showFormForSetting”) public String setActor(Model model) { model.addAttribute(“someactor”, new Actor()); return “ActorJSPNewActorForm”; } @RequestMapping(“/setActor”) public String setActor(@ModelAttribute(“someactor”) Actor actor, Model model){ //теперь используем sertviceObj sertviceObj.setActor(actor);; return “redirect:/actor/getListOfActors”; } @RequestMapping(“/deleteActor”) public String deleteActor( @RequestParam(“actorId”) int actorid, Model model) { //теперь используем sertviceObj sertviceObj.deleteActor(actorid);; return “redirect:/actor/getListOfActors”; } }

Также не забываем убрать Transactional в ДАО классе. Эти аннотации теперь в сервис классе.

package com.MavenWebAps.hibernateCRUDap.dao; import java.util.List; import javax.transaction.Transactional; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import com.MavenWebAps.hibernateCRUDap.entity.Actor; @Repository public class ActorDAOImpl implements ActorDAO { @Autowired private SessionFactory sessionFactory; //@Transactional public Actor getActor(int actorId) { Session session = sessionFactory.getCurrentSession(); return session.get(Actor.class, actorId); } //@Transactional public void setActor(Actor actor) { Session session = sessionFactory.getCurrentSession(); session.saveOrUpdate(actor); } //@Transactional public List getListOfActors() { Session session = sessionFactory.getCurrentSession(); return session.createQuery(“from Actor”, Actor.class).getResultList(); } //@Transactional public void deleteActor(int actorid) { Session session = sessionFactory.getCurrentSession(); session.createQuery( “delete from Actor where id=:actorid”) .setParameter(“actorid”, actorid).executeUpdate(); } }

Давайте же перейдем на главную страницу со списком актеров. Как мы помним, на эту страницу можно перейти через обработчик getListOfActors. Сделаем это:

Как видим, страница успешно открылась. Работает здесь всё аналогично предыдущему уроку, только теперь с сервисным уровнем.

Что такое REST API?

REST API — стандарт обмена данными между приложениями через HTTP. Форматы JSON/XML, принципы работы, примеры API Facebook и тестирование запросов.
Time to read: 21

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

Создайте Spring REST API с нуля: настройте контроллеры, конвертацию JSON в объекты и обратно с Jackson. Примеры GET-запросов и тестирование через Rest Client.
Time to read: 22

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

Пошаговое создание RESTful API для CRUD операций. Обмен данными в JSON, работа с EntityManager и Hibernate SessionFactory.
Time to read: 20