Бесплатный курс по Java: от основ до продвинутого уровня
Создание CRUD-приложения с Hibernate и Spring
В этом уроке создадим простое CRUD приложение с использованием hibernate.
CRUD это аббревиатура:
C (Create) – Добавить новые данные в БД.
R (Read) – Прочитать данные из БД.
U (Update) – Обновить данные в БД.
D (Delete) – удалить данные из БД.
Наше приложение будет реализовывать все эти четыре операции.
Эти операции будут производиться с таблицей. Пускай это будет таблица "Актеры" с аттрибутами "Имя актера" и "Самый известный фильм".
Приложение будет выглядеть примерно так:
Как видим, здесь есть ссылка add actor, которая ведет на другую страницу на которой есть форма для добавления нового актера в таблицу с актерами. Это Create операция.
Рядом с каждым актером есть ссылка update, которая ведет на другую страницу на которой есть форма для обновления данных актера рядом с которым была нажата эта ссылка. Это, очевидно, Update операция.
Также рядом с каждым актером есть ссылка для удаления конкретного актера. Это, очевидно, Delete операция.
Read же операция, это само присутствие на странице списка актеров. То есть, чтобы отобразить на странице список актеров, нужно их сначала выбрать из БД, то есть совершить Read операцию.
Давайте для начала создадим таблицу actor, в которой будут храниться актеры. И сразу туда добавим пару актеров.
Создадим Мавен приложение с такой структурой и файлами:
В папке entity хранятся классы связанные с таблицами в БД с помощью hibernate. В данном случае будет всего один класс actor, который будет связан с таблицей с актерами.
В папке controller есть класс контроллер, который будет принимать запросы, перенаправлять на страницы и совершать CRUD операции через DAO объект, который находиться в папке dao.
Daoобъект нужен для взаимодействия с БД. О нем подробнее далее.
Также можно увидеть три страницы jsp. ListOfActors отображает всех актеров из таблицы с актерами (это та страница, которую можно увидеть на картинке выше), страница ActorJSPNewActorForm на которой можно добавить нового актера в БД и страница ActorJSPUpdateForm на которой можно обновить актера в БД.
Теперь давайте добавим необходимые зависимости в pom файл, чтобы приложение работало.
Как мы помним, в обычном hibernate приложении подключение к базе настраивается в файле hibernate.cfg.xml.
В MVC же приложении подключение настраивается в applicationContext.xml.
Здесь же настраивается и бин SessionFactory, то есть создавать объект SessionFactory java кодом, как в обычном hibernate приложении не придется, создавать новые объекты сессий можно будет через заранее сконфигурированный в applicationContext бин.
org.hibernate.dialect.MySQLDialect
true
Создадим класс ранее созданной таблицы actor. Здесь ничего нового.
package com.MavenWebAps.hibernateCRUDap.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Table(name = “actor”)
public class Actor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = “id”)
private int id;
@Column(name = “name”)
private String actorName;
@Column(name = “most_famous_film”)
private String film;
public Actor() {
}
public Actor(String actorName, String film) {
this.actorName = actorName;
this.film = film;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getActorName() {
return actorName;
}
public void setActorName(String actorName) {
this.actorName = actorName;
}
public String getFilm() {
return film;
}
public void setFilm(String film) {
this.film = film;
}
@Override
public String toString() {
return “Actor [id=” + id +
“, actorName=” + actorName +
“, film=” + film + “]”;
}
}
Давайте для начала создадим интерфейс на основе которого будем создавать DAO класс.
package com.MavenWebAps.hibernateCRUDap.dao;
import java.util.List;
public interface ActorDAO {
public Actor getActor(int actorId);
public void setActor(Actor actor);
public List getListOfActors();
public void deleteActor(int actorid);
}
Через DAO бин, который будет внедряться в контроллер, будут производиться CRUD операции с БД.
В DAO классе ниже можно увидеть методы с помощью которых происходит непосредственное взаимодействие с БД с помощью hiberante.
Также важно отметить, что DAO бин, это особенный бин, класс которого помечается аннотацией @Repository.
package com.MavenWebAps.hibernateCRUD.dao;
import java.util.List;
//Также как и @Controller аннотация @Repository
//наследуется от @Component, потому спринг
//анализирует этот класс как особый бин.
//Этой аннотацией помечется DAO объект.
//Спринг распознает объект помеченный этой аннотацией
//как дао объект и благодаря этому
//в нем можно использовать @Transactional.
@Repository
//Помните паттерн ДАО. Где все низкоуровневое
//взаимодействие с ресурсом (в нашем случае с БД)
//скрывалось в дополнительном классе. В Spring MVC он
//используется для сокрытия низкоуровневого
//взаимодействия с базой с помощью hibernate.
//В этом классе мы создаем методы для взаимодействия
//с базой. В конторллере же мы используем эти методы,
//то есть никакого hibernate кода в контроллере нет
//и не должно быть.
public class ActorDAOImpl implements ActorDAO {
@Autowired
//Внедряем sessionFactory (такой же id имеет бин фабрики
//сессий который мы конфигурировали в applicationContext).
private SessionFactory sessionFactory;
//READ
//Ниже метод для выборки актера из базы по id.
//Все что выполняется в методе помеченном @Transactional
//выполняется в отдельной транзакции. То есть это просто
//некоторое упрощение чтобы нам не приходилось писать
//session.beginTransaction(); и
//session.getTransaction().commit();.
@Transactional
public Actor getActor(int actorId) {
Session session = sessionFactory.getCurrentSession();
return session.get(Actor.class, actorId);
}
//CREATE, UPDATE
//метод для вставки актера в базу ли обновления
//актера в базе.
@Transactional
public void setActor(Actor actor) {
Session session = sessionFactory.getCurrentSession();
//Есть довольно удобный метод saveOrUpdate, который
//будет смотреть на id присланного объекта actor.
//Если актер с таким id уже есть в таблице с актерами
//то этот метод обновляет строку таблицы с таким id,
//а если такого нет то добавляет присланный объект
//в таблицу.
session.saveOrUpdate(actor);
}
//Тоже READ только всех актеров,
//а не одного как метод getActor.
@Transactional
public List getListOfActors() {
Session session = sessionFactory.getCurrentSession();
return session.createQuery(“from Actor”,
Actor.class).getResultList();
}
//DELETE
//метод для удаления актера из базы по id
@Transactional
public void deleteActor(int actorid) {
Session session = sessionFactory.getCurrentSession();
session.createQuery(
“delete from Actor where id=:actorid”)
.setParameter(“actorid”, actorid).executeUpdate();
}
}
Теперь создадим контроллер, который будет перенаправлять на страницы и совершать CRUD операции через DAO бин, который внедряется в контроллер.
package com.MavenWebApps.hibernateCRUD.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.MavenWebApps.hibernateCRUD.dao.ActorDAO;
import com.MavenWebApps.hibernateCRUD.entity.Actor;
import java.util.List;
@Controller
@RequestMapping(“/actor”)
public class CRUDController {
//Внедряем созданный DAO объект (бин) чтобы
//через него взаимодействовать с базой.
@Autowired
private ActorDAO actorDao;
//READ
//Как можно увидеть этот обработчик выбирает
//из БД всех актеров через DAO объект
//и перенаправляет их в аттрибуте
//listofactors на страницу ListOfActors.jsp
//где все актеры из аттрибута будут отображены.
@RequestMapping(“/getListofActors”)
public String getListofActors(Model model) {
model.addAttribute(“listofactors”,
actorDao.getListofActors());
return “ListofActorsJSP”;
}
//Этот обработчик перенаправляет на страницу
//ActorJSPUpdateForm.jsp на которой можно
//совершить UPDATE актера. Как видим в обработчик
//передаеться id актера, по этому id выбираеться
//из БД актер и помещаеться в аттрибут someactor
//и данные этого актера из этого аттрибута будут
//отображаться на странице ActorJSPUpdateForm.jsp.
//Это просто нужно чтобы при обновлении данных
//актера мы видели на странице и предидущие
//данные обновляемого актера.
@RequestMapping(“/showFormForUpdating”)
public String showFormForUpdating(
@RequestParam(“actorId”) int actorId,
Model model) {
model.addAttribute(“someactor”,
actorDao.getActor(actorId));
return “ActorJSPUpdateForm”;
}
//Этот обработчик перенаправляет на страницу
//ActorJSPNewActorForm.jsp на которой можно
//совершить CREATE актера. То есть создать
//нового актера и поместить в таблицу с актерами.
//Как видим здесь создаеться новый обьект актера
//и помещаеться в аттребут someactor, который
//будет доступен на странице
//ActorJSPNewActorForm.jsp. Там этот обьект будет
//заполняться через форму и добавляться в БД.
@RequestMapping(“/showFormForSetting”)
public String setActor(Model model) {
model.addAttribute(“someactor”,
new Actor());
return “ActorJSPNewActorForm”;
}
//CREATE, UPDATE
//Этот обработчик просто добавляет актера
//в таблицу или обновляет актера в таблице
//с актерами и перенаправляет обратно
//на страницу со списком актеров через
//обработчик getListofActors.
@RequestMapping(“/setActor”)
public String setActor(@ModelAttribute(“someactor”) Actor actor, Model model){
actorDao.setActor(actor);
//ВАЖНЫЙ момент чтобы перейти в какой-то
//обработчик контроллера, а не на какую-то
//страницу пишем redirect:…
return “redirect:/actor/getListofActors”;
}
//DELETE
//Этот обработчик удаляет актера из таблицы
//с актерами и перенаправляет обратно
//на страницу со списком актеров через
//обработчик getListofActors.
@RequestMapping(“/deleteActor”)
public String deleteActor(
@RequestParam(“actorId”) int actorid,
Model model) {
actorDao.deleteActor(actorid);
return “redirect:/actor/getListofActors”;
}
}
Создадим главную страницу на которой будут отображаться все актеры из таблицы actor, и даются ссылки для create, updete, delete актеров.
Теперь создадим страницу с формой для добавления нового актера в таблицу актеров.
<%@ taglib prefix="form"
uri="http://www.springframework.org/tags/form"%>
<%@ page isELIgnored="false"%>
Create JSP
Name:
Most famous film:
Теперь создадим страницу с формой для обновления данных существующего актера.
<%@ taglib prefix="form"
uri="http://www.springframework.org/tags/form"%>
<%@ page isELIgnored="false"%>
Update JSP
Old Info: Old name: ${someactor.actorName},
Old film: ${someactor.film}
New Info:
Name:
Most famous film:
Давайте же перейдем на главную страницу со списком актеров. Как мы помним, на эту страницу можно перейти через обработчик getListOfActors. Сделаем это:
Как видим, обработчик getListOfActorsуспешно выбрал актеров из БД и они успешно вывелись на странице.
Давайте теперь добавим актера в БД. Для этого нажмем на add actor. В результате этого произойдет переход в обработчик showFormForSetting, который создает новый объект актера, который будет заполняться формой на странице на которую переводит этот обработчик. Ниже эта страница. Заполним форму новым актером и нажмем submit.
По нажатию на submit происходит вызов обработчика setActor, который добавляет актера в БД и перенаправляет в обработчик getListOfActors, который перенаправляет обратно на главную страницу со всеми актерами.
Как видим, новый актер успешно был добавлен в БД и отображен на странице.
Теперь давайте нажмем на Update рядом с актером Johnny Depp, чтобы можно было обновить данные этого актера. По нажатию происходит вызов обработчика showFormForUpdating, который перенаправляет на страницу для обновления данных актера. Как можно увидеть, этот обработчик успешно выбрал из БД текущие данные актера Johnny Depp, которые впоследствии были отображены на странице.
Объект актера Johnny Depp извлеченный обработчиком был связан с формой для обновления данных актера. Давайте изменим этой формой название фильма и нажмем submit.
По нажатию на submit происходит вызов обработчика setActor, который обновляет данные актера в БД и перенаправляет в обработчик getListOfActors, который перенаправляет обратно на главную страницу со всеми актерами.
Как видим, данные актера Johnny Depp, а именно название фильма, успешно обновились на странице, а значит и в БД.
Давайте теперь удалим из БД последний фильм, для этого просто нажмем Delete напротив актера Jeffrey Dean Morgan.
Как видим, актер успешно удалился на странице, а значит и в БД.
Создайте Spring REST API с нуля: настройте контроллеры, конвертацию JSON в объекты и обратно с Jackson. Примеры GET-запросов и тестирование через Rest Client.