JavaRush /Java blogi /Random-UZ /Maven, Spring, MySQL, Hibernate va birinchi CRUD ilovasig...
Макс
Daraja

Maven, Spring, MySQL, Hibernate va birinchi CRUD ilovasiga kirish (2-qism)

Guruhda nashr etilgan
Hayrli kun. Ushbu maqolada men oddiy CRUD ilovasini yaratish jarayonida Maven, Spring, Hibernate, MySQL va Tomcat kabi narsalar bilan birinchi uchrashuvimni baham ko'rmoqchiman. Bu 4-ning ikkinchi qismi. Maqola, birinchi navbatda, bu yerda 30-40 darajani tamomlagan, lekin hali sof Java-dan tashqariga chiqmagan va endigina ochiq dunyoga kirishni boshlayotgan (yoki boshlamoqchi bo'lgan)lar uchun mo'ljallangan. bu barcha texnologiyalar, ramkalar va boshqa notanish so'zlar. Bu “Maven, Spring, MySQL, Hibernate va birinchi CRUD ilovasiga kirish” maqolasining ikkinchi qismi. Birinchi qismni ushbu havola orqali ko'rish mumkin: Maven, Spring, MySQL, Hibernate va birinchi CRUD ilovasiga kirish (1-qism)

Tarkib:

Keling, davom etaylik, keling, filmlarning butun omborini sehrlashga harakat qilaylik. Bizning kichik va oddiy dasturimizda, albatta, siz ahmoqona ravishda barcha mantiqni boshqaruvchiga qo'yishingiz mumkin, ammo yuqorida aytib o'tilganidek, hamma narsani qanday qilib to'g'ri qilishni darhol o'rganish yaxshiroqdir. Shuning uchun, keling, bir nechta qatlamlarni yarataylik. Bizda ma'lumotlar bilan ishlash uchun mas'ul bo'lgan DAO , Xizmat bo'ladi , bu erda boshqa har qanday mantiq bo'ladi va Controller faqat so'rovlarni qayta ishlaydi va kerakli xizmat usullarini chaqiradi.

Ma'lumotlarga kirish ob'ekti

Ma'lumotlarga kirish ob'ekti (DAO) shunday dizayn namunasidir. Gap shundaki, ma'lumotlarga kirish (ma'lumotlar bazasi yoki boshqa saqlash mexanizmi bilan ishlash) uchun faqat javobgar bo'ladigan maxsus qatlam yaratish. Paketda daobiz interfeys yaratamiz, FilmDAOunda qo'shish, o'chirish va hk kabi usullar mavjud. Men ularni biroz boshqacha chaqirdim, lekin ular asosiy CRUD operatsiyalariga mos keladi ( C reate, Read , U pdate, D elete).

Shuni ta'kidlash kerakki, DAO-dan tashqari, Repository kabi yondashuv ham mavjud, ular juda o'xshash ko'rinadi, ikkalasi ham ma'lumotlar bilan ishlash uchun ishlatiladi. Men bu yondashuvlar qanday xususiyatlarga ega ekanligini va ular orasidagi farq nima ekanligini hali tushunmadim. Shuning uchun, men bu erda adashgan bo'lishim mumkin va buni Tao emas, balki ombor deb atash kerak yoki bu ularning orasidagi narsadir. Ammo men ko'rgan va o'rgangan ko'pgina misollarda bu DAO deb ataladi, shuning uchun men uni xuddi shunday deb atayman. Shu bilan birga, ehtimol matnning boshqa joyida men ombor so'zidan foydalanaman. Qanday bo'lmasin, agar biror joyda xato qilsam, meni kechiring.

package testgroup.filmography.dao;

import testgroup.filmography.model.Film;

import java.util.List;

public interface FilmDAO {
    List<Film> allFilms();
    void add(Film film);
    void delete(Film film);
    void edit(Film film);
    Film getById(int id);
}
Endi biz uni amalga oshirishga muhtojmiz. Biz hali ma'lumotlar bazasini ulamaymiz, bu hali ham biroz qo'rqinchli. Mashq qilish va unga ko'nikish uchun avval xotirada saqlashni simulyatsiya qilaylik va bir nechta filmlar ro'yxatini yarataylik. Roʻyxatni saqlash uchun biz butun roʻyxatni koʻzdan kechirmasdan , maʼlum bir filmni uning orqali olish qulay boʻlishi uchun emas, Listbalki dan foydalanamiz. Avlod uchun biz AtomicInteger dan foydalanamiz . Keling, sinf yaratamiz , barcha usullarni qo'llaymiz va xaritani to'ldiramiz. Shunga o'xshash narsa. MapididFilmDAOImpl
package testgroup.filmography.dao;

import testgroup.filmography.model.Film;

import java.util.*;

public class FilmDAOImpl implements FilmDAO {
    private static final AtomicInteger AUTO_ID = new AtomicInteger(0);
    private static Map<Integer, Film> films = new HashMap<>();

    static {
        Film film1 = new Film();
        film1.setId(AUTO_ID.getAndIncrement());
        film1.setTitle("Inception");
        film1.setYear(2010);
        film1.setGenre("sci-fi");
        film1.setWatched(true);
        films.put(film1.getId(), film1);

        // + film2, film3, film4, ...
    }
    @Override
    public List<Film> allFilms() {
        return new ArrayList<>(films.values());
    }

    @Override
    public void add(Film film) {
        film.setId(AUTO_ID.getAndIncrement());
        films.put(film.getId(), film);
    }

    @Override
    public void delete(Film film) {
        films.remove(film.getId());
    }

    @Override
    public void edit(Film film) {
        films.put(film.getId(), film);
    }

    @Override
    public Film getById(int id) {
        return films.get(id);
    }
}

Xizmat

Endi xizmat qatlamini qo'shamiz. Aslida, bu misolda DAO bilan cheklanib qolmasdan, buni amalga oshirish juda mumkin, dastur juda oddiy bo'ladi va xizmatda hech qanday murakkab mantiq uchun rejalar yo'q. Ammo kelajakda to'satdan siz loyihaga har xil murakkabliklar va qiziqarli narsalarni qo'shishni xohlaysiz, shuning uchun to'liqlik uchun shunday bo'lsin. Hozircha u DAO dan usullarni chaqiradi. Paketda serviceinterfeys yarataylik FilmService.
package testgroup.filmography.service;

import testgroup.filmography.model.Film;

import java.util.List;

public interface FilmService {
    List<Film> allFilms();
    void add(Film film);
    void delete(Film film);
    void edit(Film film);
    Film getById(int id);
}
Va uni amalga oshirish:
package testgroup.filmography.service;

import testgroup.filmography.dao.FilmDAO;
import testgroup.filmography.dao.FilmDAOImpl;
import testgroup.filmography.model.Film;

import java.util.List;

public class FilmServiceImpl implements FilmService {
    private FilmDAO filmDAO = new FilmDAOImpl();

    @Override
    public List<Film> allFilms() {
        return filmDAO.allFilms();
    }

    @Override
    public void add(Film film) {
        filmDAO.add(film);
    }

    @Override
    public void delete(Film film) {
        filmDAO.delete(film);
    }

    @Override
    public void edit(Film film) {
        filmDAO.edit(film);
    }

    @Override
    public Film getById(int id) {
        return filmDAO.getById(id);
    }
}
Endi loyiha tuzilishi quyidagicha ko'rinadi:
Maven, Spring, MySQL, Hibernate va birinchi CRUD ilovasiga kirish (2-qism) - 1

Controller va Views

Endi kontroller usullari va sahifalarni to'ldirish ustida ishlaylik. Sahifalarni to'ldirishda bizga ba'zi texnikalar kerak bo'ladi. Masalan, filmlar ro'yxatini ko'rsatish uchun bizga pastadir kerak, aytaylik, ba'zi yozuvlarni o'zgartirmoqchi bo'lsak, parametrlarga qarab, bizga shartlar kerak va hokazo. JSP (JavaServer Pages) formati bularning barchasini amalga oshirish mumkin bo'lgan java kod qo'shimchalaridan foydalanish imkonini beradi. Lekin men sahifada HTML kod bilan aralashtirilgan java kodidan foydalanishni xohlamayman. Bu, hech bo'lmaganda, juda xunuk bo'lar edi. Yaxshiyamki, bu muammoni hal qilish uchun JSTL (JavaServer Pages Standard Tag Library) yoki JSP Standard Tag Library kabi ajoyib narsa mavjud . Bu bizga JSP sahifalarimizda turli xil ehtiyojlar uchun qo'shimcha teglardan foydalanish imkonini beradi. Keling, uni bog'laymiz pom.xml:
<dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
</dependency>
Endi kontrollerni ko'rib chiqaylik. Avvalo, u erdan ob'ektni yaratishni olib tashlaymiz Film, bu sinov uchun qilingan va bizga boshqa hech narsa kerak emas. Keling, u erga xizmat qo'shamiz va uning usullarini chaqiramiz.
public class FilmController {
    private FilmService filmService = new FilmServiceImpl();
Shunga ko'ra, biz har bir holat uchun usullarni yaratamiz, qo'shamiz, o'chiramiz va hokazo. Avval filmlar ro'yxati bilan asosiy sahifani ko'rsatish usuli:
@RequestMapping(method = RequestMethod.GET)
    public ModelAndView allFilms() {
        List<Film> films = filmService.allFilms();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("films");
        modelAndView.addObject("filmsList", films);
        return modelAndView;
    }
Bu yerda hech qanday yangilik yo‘q. Xizmatdan filmlar ro'yxatini olamiz va uni modelga qo'shamiz. films.jspKeling , ushbu usul qaytaradigan asosiy sahifani yarataylik :
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>FILMS</title>
</head>
<body>

<h2>Films</h2>
<table>
    <tr>
        <th>id</th>
        <th>title</th>
        <th>year</th>
        <th>genre</th>
        <th>watched</th>
        <th>action</th>
    </tr>
    <c:forEach var="film" items="${filmsList}">
        <tr>
            <td>${film.id}</td>
            <td>${film.title}</td>
            <td>${film.year}</td>
            <td>${film.genre}</td>
            <td>${film.watched}</td>
            <td>
                <a href="/edit/${film.id}">edit</a>
                <a href="/delete/${film.id}">delete</a>
            </td>
        </tr>
    </c:forEach>
</table>

<h2>Add</h2>
<c:url value="/add" var="add"/>
<a href="${add}">Add new film</a>
</body>
</html>
Keling, nima ekanligini bilish uchun ushbu sahifani batafsil ko'rib chiqaylik. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - bu erda JSTL yadrosi ulangan, u tsikllar, shartlar va hokazolarni yaratish uchun asosiy teglarni o'z ichiga oladi. .
  • <table>— jadval yaratish uchun teg.
  • <tr>- stol qatori
  • <th>- ustun sarlavhasi
  • <td>- stol katakchasi
Birinchidan, ustunlar nomlari bilan jadval sarlavhasi qatorini qilamiz. Keyin <c:forEach var="film" items="${filmsList}">, tsiklda (biz JSTL yadrosidan oldik) biz o'tgan ro'yxatning barcha elementlarini ( filmsList), har bir element uchun ( film) yangi qator yaratamiz va har bir katakka mos keladigan qiymatni yozamiz. Bu erda bir nuqta bor, yozuvni film.idtushunish kerak ko'rinadi film.getId(), ya'ni. Maydonga to'g'ridan-to'g'ri kirish mumkin emas, lekin oluvchi chaqiriladi. Oxirgi ustunda ( action) biz o'chirish va tahrirlash uchun havolalar qilamiz (hozir tegishli usullarni yaratamiz). Xo'sh, quyida yangi film qo'shish usuliga havola. Bu shunday ko'rinadi: Keyinchalik, ma'lum bir film uchun tahrirlash sahifasini qaytaradigan usulni ko'rib chiqamiz:
@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
    public ModelAndView editPage(@PathVariable("id") int id) {
        Film film = filmService.getById(id);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("editPage");
        modelAndView.addObject("film", film);
        return modelAndView;
    }
Bu yerda yangi narsa paydo bo'ldi - bu izoh @PathVariable. int idBu parametr ( ) manzil satridan olinganligini bildiradi . Ushbu parametrning manzil satrida joylashgan joyini ko'rsatish uchun konstruktsiyadan foydalaniladi {id}(aytmoqchi, agar o'zgaruvchining nomi bu holatda bo'lgani kabi bir xil bo'lsa, uni qavs ichida ko'rsatish shart emas, shunchaki yozing. @PathVariable int id). Shunday qilib, asosiy sahifada biz har bir film uchun quyidagi havolalarni yaratdik id:
<a href="/edit/${film.id}">edit</a>
Keyin bu qiymat usul parametriga tayinlanadi va keyin biz uni xizmat orqali ombordan ma'lum bir filmni olish va uni modelga qo'shish uchun ishlatamiz. Bu tahrirlash sahifasini olish usuli edi, endi bizga o'zini tahrirlash usuli kerak:
@RequestMapping(value = "/edit", method = RequestMethod.POST)
    public ModelAndView editFilm(@ModelAttribute("film") Film film) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("redirect:/");
        filmService.edit(film);
        return modelAndView;
    }
Usulda editPagebiz modelga atribut qo'shdik:
modelAndView.addObject("film", filmService.getById(id));
Va endi izoh yordamida @ModelAttributebiz ushbu atributni olamiz va uni o'zgartirishimiz mumkin. So'rov usuli POST, chunki bu erda biz ma'lumotlarni uzatamiz. " redirect:/" bu usulni bajarganimizdan so'ng biz " " manziliga yo'naltirilamiz /, ya'ni. usul ishga tushadi allFilmsva biz asosiy sahifaga qaytamiz. Endi sahifani o'zi yarataylik editPage.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Edit</title>
</head>
<body>
<c:url value="/edit" var="var"/>
<form action="${var}" method="POST">
    <input type="hidden" name="id" value="${film.id}">
    <label for="title">Title</label>
    <input type="text" name="title" id="title">
    <label for="year">Year</label>
    <input type="text" name="year" id="year">
    <label for="genre">Genre</label>
    <input type="text" name="genre" id="genre">
    <label for="watched">Watched</label>
    <input type="text" name="watched" id="watched">
    <input type="submit" value="Edit film">
</form>
</body>
</html>
  • <form>- ma'lumotlarni yig'ish va jo'natish uchun shakl, uni kim qayta ishlashini ko'rsatadi ( /edit)
  • <input>— foydalanuvchi oʻzaro aloqasi uchun interfeys elementlari (tugmalar, kiritish maydonlari va h.k.)
  • <label>- matn belgisi
Shunday qilib, tugmani bosganingizda, <input type="submit" value="Edit film">formadagi ma'lumotlar serverga yuboriladi ( idserver ma'lumotlar bazasidagi qaysi yozuvni yangilash kerakligini bilishi uchun qiymatga ega ko'rinmas maydon maxsus qo'shilgan). Usulda editFilmular tegishli atribut maydonlariga tayinlanadi film. Keyin yangilangan ro'yxat bilan asosiy sahifaga qaytamiz. Tahrirlash sahifasi quyidagicha ko'rinadi: Endi ro'yxatga yangi filmlarni qo'shishni boshlaylik. Buni amalga oshirish uchun sizga ma'lumotlarni kiritish va yuborish uchun forma kerak bo'ladi. Siz asosiy sahifada shakl yaratishingiz yoki alohida sahifa yaratishingiz mumkin, masalan editPage.jsp. Ammo, boshqa tomondan, qo'shish shakli tahrirlash bilan bir xil bo'ladi, ya'ni. 4 ta kiritish maydoni va yuborish tugmasi. Xo'sh, nima uchun yangi sahifa yarating, keling editPage.jsp. Sahifani olish usuli:
@RequestMapping(value = "/add", method = RequestMethod.GET)
    public ModelAndView addPage() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("editPage");
        return modelAndView;
    }
Usulda editPagebiz atributni keyinroq o'zgartirish uchun qo'shimcha ravishda o'tkazdik, ammo bu erda biz shunchaki sahifani olamiz. Va qo'shish usuli:
@RequestMapping(value = "/add", method = RequestMethod.POST)
    public ModelAndView addFilm(@ModelAttribute("film") Film film) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("redirect:/");
        filmService.add(film);
        return modelAndView;
    }
Biz bu erda atributni o'tkazmaganimiz sababli, bu erda yangi ob'ekt yaratiladi Film. Xo'sh, bu erda yangi narsa yo'q. Shuni ham ta'kidlash kerakki, bizda ikkala usul ham " /add" da mavjud. Bu har xil turdagi so'rovlarga javob berishlari tufayli mumkin. Asosiy sahifadagi havola bo'yicha biz GET so'rovini qilamiz, bu bizni addPage. Va qo'shish sahifasida ma'lumotlarni yuborish tugmachasini bosganimizda, POST so'rovi amalga oshiriladi va addFilm. Yangi film qo'shish uchun biz tahrirlash sahifasidan foydalanishga qaror qildik. Ammo u erda ma'lumotlar " " manziliga yuboriladi /edit:
<c:url value="/edit" var="var"/>
<form action="${var}" method="POST">
    <input type="submit" value="Edit film">
</form>
Biz sahifani biroz o'zgartirishimiz kerak, shunda u qo'shish va tahrirlashda boshqacha harakat qiladi. Ushbu muammoni hal qilish uchun biz bir xil JSTL yadro kutubxonasi shartlaridan foydalanamiz:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <c:if test="${empty film.title}">
        <title>Add</title>
    </c:if>
    <c:if test="${!empty film.title}">
        <title>Edit</title>
    </c:if>
</head>
<body>
<c:if test="${empty film.title}">
    <c:url value="/add" var="var"/>
</c:if>
<c:if test="${!empty film.title}">
    <c:url value="/edit" var="var"/>
</c:if>
<form action="${var}" method="POST">
    <c:if test="${!empty film.title}">
        <input type="hidden" name="id" value="${film.id}">
    </c:if>
    <label for="title">Title</label>
    <input type="text" name="title" id="title">
    <label for="year">Year</label>
    <input type="text" name="year" id="year">
    <label for="genre">Genre</label>
    <input type="text" name="genre" id="genre">
    <label for="watched">Watched</label>
    <input type="text" name="watched" id="watched">
    <c:if test="${empty film.title}">
        <input type="submit" value="Add new film">
    </c:if>
    <c:if test="${!empty film.title}">
        <input type="submit" value="Edit film">
    </c:if>
</form>
</body>
</html>
Bular. Biz faqat maydonni tekshirmoqdamiz film.title. Agar u bo'sh bo'lsa, unda bu yangi film, biz uning uchun barcha ma'lumotlarni to'ldirishimiz va uni ro'yxatga qo'shishimiz kerak. Agar bu maydon bo'sh bo'lmasa, u ro'yxatdagi film va siz uni o'zgartirishingiz kerak. Bu. Biz sahifamizning ikkita versiyasini olamiz: Filmni ro'yxatdan olib tashlashning oxirgi boshqaruv usuli:
@RequestMapping(value="/delete/{id}", method = RequestMethod.GET)
    public ModelAndView deleteFilm(@PathVariable("id") int id) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("redirect:/");
        Film film = filmService.getById(id);
        filmService.delete(film);
        return modelAndView;
    }
Menimcha, bu erda hech narsani izohlashning hojati yo'q, bularning barchasi allaqachon ko'rib chiqilgan. Biz allaqachon asosiy sahifada ushbu manzilga havolalar yaratdik. Xo'sh, bu erda hamma narsa tayyor ko'rinadi, siz uni qayta ishga tushirishingiz va hamma narsa qanday ishlashini ko'rishingiz mumkin.

Repozitariy va xizmat bahor komponentlari sifatida

Keling, yana bir kichik tuzatish kiritamiz. Gap shundaki, endi bizning saqlashimiz va xizmatimiz shunchaki sinflar va ulardan foydalanish uchun biz o'zimiz sinf ob'ektini yaratishimiz kerak ( new FilmServiceImpl()). Lekin bizda Bahor bir sababga ko'ra bog'langan , shuning uchun bu masalani o'zi nazorat qilsin. Sinflarimizni Bahor nazorati ostiga qo'yish uchun ularning tarkibiy qismlari ekanligini ko'rsatishimiz kerak. Buning uchun biz ularni maxsus izohlar bilan belgilaymiz:
@Repository
public class FilmDAOImpl implements FilmDAO {
@Service
public class FilmServiceImpl implements FilmService {
Izohlar @Repositoryva @Service, shuningdek @Controllerdan olingan @Component. Ushbu uchta izohning o'ziga xos xususiyatlari va farqlari qanday va ular oddiy komponentdan qanday farq qiladi, hujjatlar yoki qo'llanmalarda alohida o'qilishi kerak. Hozircha, bu izohlar Bahorga bu sinflar mos ravishda ombor va xizmat ekanligini bildirishini bilish kifoya. Va endi biz ushbu sinflarning aniq ob'ektlarini o'zimiz yaratishimiz shart emas:
private FilmService filmService = new FilmServiceImpl();
Buning o'rniga, siz maydonni maxsus izoh bilan belgilashingiz mumkin va Spring tegishli dasturni tanlaydi:
@Autowired
private FilmService filmService;
Izoh @Autowired(avtomatik bog'lash) Bahorga uning kontekstiga kirib, bu erda mos loviya almashtirishi kerakligini aytadi. Juda qulay. Agar ilgari biz usullarni o'ziga xos tarzda amalga oshirish haqida tashvishlanmaslik uchun interfeyslardan foydalangan bo'lsak, endi interfeysning o'zini amalga oshirish haqida tashvishlanishimiz va hatto uning nomini bilishimiz shart emas. G'oya shundan iboratki, maydonda avtomatik bog'lanishdan foydalanish tavsiya etilmaydi, konstruktor yoki sozlash vositasidan foydalanish yaxshiroqdir. Bu haqda ko'proq hujjatlarda o'qing. Biz uchun, printsipial jihatdan, bu muhim emas, biz uni xavfsiz tarzda shunday qoldiramiz. Ammo, g'oya buni talab qilganligi sababli, biz hamma narsa chiroyli va sariq ogohlantirishlarsiz ekanligini hurmat qilamiz. Controller sinfida sozlagich yaratamiz va unga izoh beramiz:
@Controller
public class FilmController {

    private FilmService filmService;

    @Autowired
    public void setFilmService(FilmService filmService) {
        this.filmService = filmService;
    }
FilmDAOVa shunga o'xshab biz sinfda uchun setter qilamiz FilmServiceImpl. Davomi... Maven, Spring, MySQL, Hibernate va birinchi CRUD ilovasi bilan tanishtirish (1-qism) Maven, Spring, MySQL, Hibernate va birinchi CRUD ilovasi bilan tanishtirish (2-qism) Maven, Spring, MySQL, Hibernate va birinchi CRUD ilovasi (3-qism) Maven, Spring, MySQL, Hibernate va birinchi CRUD ilovasiga kirish (4-qism)
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION