JavaRush /Java блогу /Random-KY /Maven, Spring, MySQL, Hibernate жана биринчи CRUD тиркеме...
Макс
Деңгээл

Maven, Spring, MySQL, Hibernate жана биринчи CRUD тиркемесине киришүү (2-бөлүк)

Группада жарыяланган
Кутмандуу күнүң менен. Бул макалада мен жөнөкөй CRUD тиркемесин түзүү процессинде Maven, Spring, Hibernate, MySQL жана Tomcat сыяктуу нерселер менен болгон биринчи жолугушуум менен бөлүшкүм келет. Бул 4-бөлүктүн экинчи бөлүгү. Макала биринчи кезекте бул жерде 30-40 денгээлди бүтүргөн, бирок таза Java чегинен чыга элек жана ачык дүйнөгө кирүү үчүн жаңыдан баштаган (же баштайын деп жаткан) үчүн арналган. бардык бул технологиялар, алHowтар ​​жана башка бейтааныш сөздөр. Бул макаланын экинчи бөлүгү "Maven, Spring, MySQL, Hibernate жана биринчи CRUD тиркемелерине киришүү." Биринчи бөлүгүн бул шилтеме аркылуу көрүүгө болот: Maven, Spring, MySQL, Hibernate жана биринчи CRUD тиркемеси менен таанышуу (1-бөлүк)

Мазмуну:

Келгиле, андан ары уланталы, келгиле, тасмалардын бүтүндөй репозиторийин ойлоп табууга аракет кылалы. Биздин кичинекей жана жөнөкөй тиркемеде, албетте, сиз жөн гана акылсыздык менен бардык логиканы контроллерге туура койсоңуз болот, бирок, жогоруда айтылгандай, баарын кантип туура жасоону дароо үйрөнүп алганыңыз жакшы. Ошондуктан, келгиле, бир нече катмарларды түзөлү. Бизде маалыматтар менен иштөө үчүн жооптуу DAO , Кызмат болот , анда башка логиканын бардык түрлөрү болот жана Контроллер сурамдарды гана иштеп чыгып, керектүү тейлөө ыкмаларын чакырат.

Маалыматтарга кирүү an objectи

Data Access Object (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, бирок , аны бүт тизмени карап отурбастан, Mapбелгилүү бир тасманы анын аркылуу алуу ыңгайлуу болушу үчүн . idМуун үчүн биз AtomicIntegerid колдонобуз . Келгиле, класс түзүп , бардык ыкмаларды ишке ашырып, картаны толтуралы. Ушундай бир нерсе. FilmDAOImpl
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

Controller and Views

Келгиле, азыр контроллердин ыкмаларын иштеп чыгып, барактарды толтуралы. Барактарды толтурууда бизге кээ бир ыкмалар керек болот. Мисалы, тасмалардын тизмесин көрсөтүү үчүн бизге цикл керек, мисалы, кээ бир жазууну өзгөрткүбүз келсе, параметрлерге жараша шарттар керек ж.б.у.с. JSP (JavaServer Pages) форматы мунун бардыгын ишке ашырууга мүмкүн болгон java codeун киргизүүнү колдонууга мүмкүндүк берет. Бирок мен баракта HTML codeу менен аралашкан java codeун колдонгум келбейт. Бул, жок эле дегенде, абдан жаман болмок. Бактыга жараша, бул маселени чечүү үчүн JSTL (JavaServer Pages Standard Tag Library) же JSP Standard Tag Library сыяктуу сонун нерсе бар . Бул ар кандай муктаждыктар үчүн биздин 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>— table түзүү үчүн белги.
  • <tr>- үстөл катар
  • <th>- мамычанын аталышы
  • <td>- үстөл клеткасы
Биринчиден, биз мамычалардын аталыштары менен tableнын баш сабын жасайбыз. Андан кийин <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ге жөнөтүлөт (маанилүү көзгө көрүнбөгөн талаа атайын кошулган, idандыктан server маалымат базасындагы кайсы жазууну жаңыртуу керек экенин билет). Методдо 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;
    }
Биз бул жерде атрибутту өткөрбөгөндүктөн, бул жерде жаңы an object түзүлөт 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. Эгерде ал бош болсо, анда бул жаңы кино, биз ал үчүн бардык маалыматтарды толтуруп, тизмеге кошуубуз керек. Бул талаа бош эмес болсо, анда бул тизмедеги тасма жана аны жөн гана өзгөртүү керек. Ошол. биз баракчабыздын эки versionсын алабыз: Тизмеден тасманы алып салуу үчүн акыркы контроллер ыкмасы:
@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;
    }
Менимче, бул жерде эч нерсеге комментарий берүүнүн кереги жок, мунун баары мурда эле каралып бүткөн. Биз буга чейин бул дарекке шилтемелерди башкы бетте жасаганбыз. Ооба, бул жерде баары даяр окшойт, аны кайра иштетип, баары кантип иштээрин көрө аласыз.

Репозиторий жана кызмат жазгы компоненттер катары

Дагы бир кичинекей оңдоо киргизели. Чындыгында, азыр биздин сактоо жана кызматыбыз жөн гана класстар жана аларды колдонуу үчүн өзүбүз класс an objectин түзүшүбүз керек ( new FilmServiceImpl()). Бирок бизде Жаздын бир себеби бар , ошондуктан бул ишти өзү көзөмөлдөсүн. Класстарыбызды Жаздын көзөмөлүнө коюу үчүн, биз алардын компоненттер экенин көрсөтүшүбүз керек. Бул үчүн, биз аларды атайын annotationлар менен белгилейбиз:
@Repository
public class FilmDAOImpl implements FilmDAO {
@Service
public class FilmServiceImpl implements FilmService {
Аннотациялар @Repositoryжана @Service, ошондой эле @Controllerалынган @Component. Бул үч annotationнын спецификалык өзгөчөлүктөрү жана айырмачылыктары эмнеде жана алар жөнөкөй компоненттен кандайча айырмаланат, documentацияда же колдонмолордо өзүнчө окуу керек. Азырынча, бул annotationлар Жазга бул класстар тиешелүүлүгүнө жараша репозиторий жана кызмат экенин айтып жатканын билүү жетиштүү. Эми бул класстардын конкреттүү an objectилерин өзүбүз жаратуунун кереги жок:
private FilmService filmService = new FilmServiceImpl();
Анын ордуна, сиз талааны атайын annotation менен белгилей аласыз жана Жаз тиешелүү ишке ашырууну тандайт:
@Autowired
private FilmService filmService;
Аннотация @Autowired(авто-байлоо) Жазга анын контекстине кирип, бул жерде ылайыктуу төө буурчакты алмаштыруу керектигин айтат. Абдан ыңгайлуу. Эгерде мурда биз методдордун конкреттүү ишке ашырылышы жөнүндө кабатыр болбоо үчүн интерфейстерди колдонсок, азыр интерфейстин өзүн ишке ашыруу жөнүндө тынчсыздануунун жана анын атын билүүнүн да кереги жок. Идея: талаада авто-байлоону колдонуу сунушталbyte, конструктор же орнотуучуну колдонуу жакшы. Бул тууралуу documentациядан окуңуз. Биз үчүн, негизи, бул маанилүү эмес, биз аман-эсен ушундай кылып калтыра алабыз. Бирок, идея аны сурап жаткандыктан, биз баары кооз жана эч кандай сары эскертүүсүз экенин сыйлайбыз. Контроллер классында, келгиле, орнотуучуну түзүп, ага annotation кылалы:
@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