JavaRush /Java блогы /Random-KK /Maven, Spring, MySQL, Hibernate және бірінші CRUD қолданб...
Макс
Деңгей

Maven, Spring, MySQL, Hibernate және бірінші CRUD қолданбасына кіріспе (2 бөлім)

Топта жарияланған
Қайырлы күн. Бұл мақалада мен қарапайым CRUD қосымшасын жасау процесінде Maven, Spring, Hibernate, MySQL және Tomcat сияқты нәрселермен алғашқы кездесуіммен бөліскім келеді. Бұл 4-тің екінші бөлімі. Мақала негізінен мұнда 30-40 деңгейді аяқтаған, бірақ әлі таза Java-дан асып кетпеген және ашық әлемге енді ғана кіруді бастаған (немесе бастағалы жатқан) адамдарға арналған. барлық осы технологиялар, фреймворктар және басқа да бейтаныс сөздер. Бұл «Maven, Spring, MySQL, Hibernate және бірінші CRUD қолданбасына кіріспе» мақаласының екінші бөлімі. Бірінші бөлімді мына сілтеме арқылы көруге болады: Maven, Spring, MySQL, Hibernate және бірінші CRUD қолданбасына кіріспе (1 бөлім)

Мазмұны:

Ал, әрі қарай жүрейік, енді фильмдердің толық репозиторийін елестетуге тырысайық. Біздің шағын және қарапайым қосымшамызда, әрине, сіз барлық логиканы контроллерге дұрыс қоюға болады, бірақ жоғарыда айтылғандай, бәрін қалай дұрыс жасау керектігін бірден үйренген дұрыс. Сондықтан бірнеше қабат жасайық. Бізде деректермен жұмыс істеуге жауапты DAO , Қызмет болады , мұнда басқа логиканың барлық түрлері болады, ал контроллер тек сұрауларды өңдейді және қажетті қызмет әдістерін шақырады.

Деректерге қол жеткізу нысаны

Деректерге қол жеткізу нысаны (DAO) осындай дизайн үлгісі болып табылады. Мәселе деректерге қол жеткізуге (деректер базасымен немесе басқа сақтау механизмімен жұмыс істеу) жалғыз жауапты болатын арнайы қабатты құру болып табылады. Пакетте біз қосу, жою және т.б. сияқты әдістер болатын daoинтерфейс жасаймыз. FilmDAOМен оларды сәл басқаша атадым, бірақ олар негізгі CRUD операцияларына сәйкес келеді ( C reate, Read , U pdate, D elete).

Бұл жерде айта кететін жайт, DAO-дан басқа, репозиторий сияқты тәсіл де бар, олар өте ұқсас болып көрінеді, екеуі де деректермен жұмыс істеу үшін қолданылады. Мен бұл тәсілдердің қандай ерекшеліктері бар екенін және олардың арасындағы айырмашылықты әлі түсінген жоқпын. Сондықтан, мен бұл жерде қателесуім мүмкін және бұл дао емес, репозиторий деп аталуы керек немесе бұл олардың арасындағы нәрсе болуы мүмкін. Бірақ мен көрген және зерттеген мысалдардың көпшілігінде бұл DAO деп аталады, сондықтан мен оны солай атайтын шығармын. Сонымен қатар, мүмкін, мәтіннің бір жерінде мен репозиторий сөзін қолданамын. Қалай болғанда да, егер мен бір жерде қателессем, мені кешіріңіз.

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);
}
Енді оны жүзеге асыру қажет. Біз дерекқорды әлі қоса алмаймыз, бұл әлі де қорқынышты. Жаттығу және оған үйрену үшін алдымен жадтағы сақтауды имитациялап, бірнеше фильмдер тізімін жасайық. Тізімді сақтау үшін біз бүкіл тізімді араламай-ақ белгілі бір фильмді оның көмегімен шығарып алуға ыңғайлы ету үшін емес, Listбірақ қолданамыз. Ұрпақ үшін біз AtomicInteger пайдаланамыз . Класс құрып , барлық әдістерді енгізіп, картаны толтырайық. Соған ұқсас нәрсе. 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);
    }
}

Қызмет

Енді қызмет көрсету деңгейін қосамыз. Негізінде, бұл мысалда өзімізді DAO-мен шектей отырып, онсыз істеуге болады, қолданба өте қарапайым болады және қызметте ешқандай күрделі логика үшін жоспарлар жоқ. Бірақ кенеттен болашақта сіз жобаға әртүрлі қиындықтар мен қызықты нәрселерді қосқыңыз келеді, сондықтан толық болу үшін бұл болсын. Әзірге ол DAO әдістерін шақырады. Пакетте serviceинтерфейс жасайық 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);
}
Және оны жүзеге асыру:
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);
    }
}
Жоба құрылымы енді келесідей көрінеді:
Maven, Spring, MySQL, Hibernate және бірінші CRUD қолданбасына кіріспе (2 бөлім) - 1

Контроллер және көріністер

Енді контроллер әдістерімен жұмыс жасап, беттерді толтырайық. Беттерді толтырған кезде бізге кейбір әдістер қажет болады. Мысалы, фильмдер тізімін көрсету үшін бізге цикл қажет, айталық, кейбір жазуды өзгерткіміз келсе, параметрлерге байланысты шарттар қажет және т.б. JSP (JavaServer Pages) пішімі осының барлығын жүзеге асыруға болатын java codeын кірістірулерді пайдалануға мүмкіндік береді. Бірақ мен бетте HTML codeымен араласқан java codeын пайдаланғым келмейді. Бұл, кем дегенде, өте ұсқынсыз болар еді. Бақытымызға орай, бұл мәселені шешу үшін JSTL (JavaServer Pages Standard Tag Library) немесе JSP стандартты тегтер кітапханасы сияқты тамаша нәрсе бар . Бұл әртүрлі қажеттіліктер үшін JSP беттерінде қосымша тегтердің тұтас жиынтығын пайдалануға мүмкіндік береді. Оны келесіге қосайық pom.xml:
<dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
</dependency>
Енді контроллерді қарастырайық. Ең алдымен, an objectінің жасалуын сол жерден алып тастаймыз Film, бұл тестілеу үшін жасалды және бізге басқа ештеңе қажет емес. Онда қызметті қосып, оның әдістерін шақырайық.
public class FilmController {
    private FilmService filmService = new FilmServiceImpl();
Сәйкесінше, біз әр жағдай үшін әдістерді жасаймыз, қосу, жою және т.б. Алдымен фильмдер тізімі бар басты бетті көрсету әдісі:
@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;
    }
Мұнда жаңа ештеңе жоқ. Біз сервистен фильмдер тізімін аламыз және оны үлгіге қосамыз. films.jspЕнді осы әдіс қайтаратын басты бетті жасайық :
<%@ 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>
Ненің не екенін көру үшін осы бетті мұқият қарастырайық. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - мұнда JSTL өзегі қосылған, ол циклдерді, шарттарды және т.б. құруға арналған негізгі тегтерді қамтиды. .
  • <table>— кесте құруға арналған тег.
  • <tr>— кесте қатары
  • <th>- баған тақырыбы
  • <td>— үстел ұяшығы
Алдымен бағандардың аттары жазылған кесте тақырыбы жолын жасаймыз. Содан кейін <c:forEach var="film" items="${filmsList}">, циклде (біз оны JSTL өзегінен алдық) біз өткен тізімнің барлық элементтерін ( filmsList) өткіземіз, әрбір элемент үшін ( film) жаңа жол жасаймыз және әрбір ұяшыққа сәйкес мәнді жазамыз. Бұл жерде бір жайт бар, жазба деп film.idтүсіну керек сияқты film.getId(), яғни. Өріске тікелей қол жеткізілмейді, бірақ алушы шақырылады. Соңғы бағанда ( action) біз жою және өңдеу үшін сілтемелер жасаймыз (қазір сәйкес әдістерді жасаймыз). Төменде жаңа фильм қосу әдісіне сілтеме берілген. Ол келесідей: Әрі қарай, белгілі бір фильмнің өңдеу бетін қайтаратын әдісті қарастырайық:
@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;
    }
Мұнда жаңа нәрсе пайда болды - бұл annotation @PathVariable. Ол бұл параметрдің ( int id) мекенжай жолағынан алынғанын көрсетеді. Мекенжай жолағында осы параметрдің орнын көрсету үшін конструкция қолданылады {id}(айтпақшы, егер айнымалы атауы осы жағдайдағыдай болса, оны жақшада көрсетудің қажеті жоқ, жай ғана жазыңыз. @PathVariable int id). Сонымен, басты бетте біз әрбір фильмге сілтемелер жасадық id:
<a href="/edit/${film.id}">edit</a>
Содан кейін бұл мән әдіс параметріне тағайындалады, содан кейін біз оны қызмет арқылы репозиторийден белгілі бір фильмді алу және оны модельге қосу үшін қолданамыз. Бұл өңдеу бетін алу әдісі болды, енді бізге өзін өңдеу әдісі қажет:
@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;
    }
Әдісте editPageбіз үлгіге атрибут қостық:
modelAndView.addObject("film", filmService.getById(id));
Ал енді annotationның көмегімен @ModelAttributeбіз бұл атрибутты аламыз және оны өзгерте аламыз. Сұраныс әдісі POST, өйткені мұнда біз деректерді жібереміз. « redirect:/» бұл әдісті орындағаннан кейін біз « » мекенжайына қайта бағытталатынымызды білдіреді /, яғни. әдіс іске қосылады allFilmsжәне біз негізгі бетке ораламыз. Енді беттің өзін жасайық 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>— деректерді кім өңдейтінін көрсететін деректерді жинау және жіберу формасы ( /edit)
  • <input>— пайдаланушының өзара әрекеттесуі үшін интерфейс элементтері (түймелер, енгізу өрістері және т.б.)
  • <label>- мәтіндік белгі
Сонымен, түймені басқан кезде <input type="submit" value="Edit film">пішіндегі деректер serverге жіберіледі ( idserver дерекқордағы қай жазбаны жаңарту қажет екенін білуі үшін мәні бар көрінбейтін өріс арнайы қосылды). Әдісте editFilmолар сәйкес атрибут өрістеріне тағайындалады film. Содан кейін жаңартылған тізіммен негізгі бетке ораламыз. Өңдеу беті келесідей: Енді тізімге жаңа фильмдерді қосуды бастайық. Мұны істеу үшін сізге деректерді енгізу және жіберу үшін пішін қажет болады. Сіз басты бетте пішін жасай аласыз немесе жеке бет жасай аласыз, мысалы editPage.jsp. Бірақ, екінші жағынан, қосу пішіні өңдеумен бірдей болады, яғни. 4 енгізу өрісі және жіберу түймесі. Ендеше, неге жаңа бет жасау керек, қолданайық editPage.jsp. Бетті алу әдісі:
@RequestMapping(value = "/add", method = RequestMethod.GET)
    public ModelAndView addPage() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("editPage");
        return modelAndView;
    }
Әдісте editPageбіз атрибутты кейінірек өзгерту үшін қосымша тапсырдық, бірақ бұл жерде біз жай ғана бетті аламыз. Және қосу әдісі:
@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;
    }
Бұл жерде атрибутты өткізбегендіктен, осы жерде жаңа нысан жасалады Film. Негізі мұнда жаңа ештеңе жоқ. Сондай-ақ, бізде екі әдістің де « » қол жетімді екенін атап өткен жөн /add. Бұл олардың әртүрлі сұрауларға жауап беруіне байланысты мүмкін. Негізгі беттегі сілтеме бойынша біз GET сұрауын жасаймыз, ол бізді addPage. Ал қосу бетінде деректерді жіберу түймешігін басамыз, POST сұрауы жасалады және addFilm. Жаңа фильм қосу үшін біз өңдеуге арналған бетті пайдалануды шештік. Бірақ ол жерде деректер " " мекенжайына жіберіледі /edit:
<c:url value="/edit" var="var"/>
<form action="${var}" method="POST">
    <input type="submit" value="Edit film">
</form>
Біз бетті сәл өзгертуіміз керек, осылайша ол қосу және өңдеу үшін басқаша әрекет етеді. Бұл мәселені шешу үшін біз JSTL негізгі кітапханасының шарттарын пайдаланамыз:
<%@ 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>
Анау. біз жай ғана өрісті тексеріп жатырмыз film.title. Егер ол бос болса, онда бұл жаңа фильм, біз оған барлық деректерді толтырып, тізімге қосуымыз керек. Егер бұл өріс бос болмаса, бұл тізімдегі фильм және оны өзгерту керек. Бұл. біз парақтың екі нұсқасын аламыз: Фильмді тізімнен алып тастаудың соңғы контроллері әдісі:
@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;
    }
Менің ойымша, бұл жерде ешнәрсеге түсініктеме берудің қажеті жоқ, мұның бәрі қарастырылған. Біз бұл мекенжайға сілтемелерді басты бетте жасадық. Мұнда бәрі дайын сияқты, оны қайтадан іске қосып, бәрі қалай жұмыс істейтінін көруге болады.

Репозиторий және қызмет көктемгі құрамдас бөліктер ретінде

Тағы бір шағын түзету жасайық. Өйткені, қазір біздің сақтауымыз бен қызметіміз тек сыныптар болып табылады және оларды пайдалану үшін біз өзіміз класс нысанын жасауымыз керек ( new FilmServiceImpl()). Бірақ бізде Көктемнің бір себебі бар , сондықтан ол бұл мәселені өзі бақылауға алсын. Сыныптарымызды көктемнің бақылауына қою үшін олардың құрамдас бөліктері екенін көрсетуіміз керек. Ол үшін біз оларды арнайы annotationлармен белгілейміз:
@Repository
public class FilmDAOImpl implements FilmDAO {
@Service
public class FilmServiceImpl implements FilmService {
Аннотациялар @Repositoryжәне @Service, сондай-ақ @Controllerалынған @Component. Осы үш annotationның қандай ерекшеліктері мен айырмашылықтары бар және олардың қарапайым құрамдас бөліктен айырмашылығы қандай, құжаттамада немесе нұсқаулықтарда бөлек оқу керек. Әзірге бұл annotationлар көктемге бұл сыныптардың сәйкесінше репозиторий және қызмет екенін көрсететінін білу жеткілікті. Енді бізге осы сыныптардың нақты an objectілерін өзіміз жасаудың қажеті жоқ:
private FilmService filmService = new FilmServiceImpl();
Оның орнына өрісті арнайы annotationмен белгілеуге болады және Spring сәйкес іске асыруды таңдайды:
@Autowired
private FilmService filmService;
Аннотация @Autowired(автоматты түрде байланыстыру) Көктемге оның контекстіне еніп, осы жерде қолайлы бұршақты ауыстыру керектігін айтады. Өте ыңғайлы. Егер бұрын біз әдістерді нақты іске асыру туралы алаңдамау үшін интерфейстерді пайдаланатын болсақ, енді интерфейстің өзін жүзеге асыру туралы алаңдамаудың және тіпті оның атын білудің қажеті жоқ. Идея мынада: өрісте автоматты байланыстыруды пайдалану ұсынылмайды, конструкторды немесе орнатушыны қолданған дұрыс. Бұл туралы толығырақ құжаттамада оқыңыз. Біз үшін, негізінен, бұл маңызды емес, біз оны осылай қалдыра аламыз. Бірақ, идея соны сұрап тұрғандықтан, біз бәрі әдемі және ешқандай сары ескертусіз екенін құрметтейміз. Контроллер класында орнатушыны жасап, оған түсініктеме берейік:
@Controller
public class FilmController {

    private FilmService filmService;

    @Autowired
    public void setFilmService(FilmService filmService) {
        this.filmService = filmService;
    }
FilmDAOСол сияқты біз сыныпта орнатушы жасаймыз FilmServiceImpl. Жалғасы бар... Maven, Spring, MySQL, Hibernate және бірінші CRUD қолданбасымен таныстыру (1-бөлім) Maven, Spring, MySQL, Hibernate және бірінші CRUD қолданбасымен таныстыру (2-бөлім) Maven, Spring, MySQL, Hibernate және бірінші CRUD қолданбасы (3-бөлім) Maven, Spring, MySQL, Hibernate және бірінші CRUD қолданбасына кіріспе (4-бөлім)
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION