JavaRush /Blog Jawa /Random-JV /Pambuka kanggo Maven, Spring, MySQL, Hibernate lan aplika...
Макс
tingkat

Pambuka kanggo Maven, Spring, MySQL, Hibernate lan aplikasi CRUD pisanan (bagean 2)

Diterbitake ing grup
sugeng sonten. Ing artikel iki aku pengin nuduhake ketemu pisanan karo bab kaya Maven, Spring, Hibernate, MySQL lan Tomcat ing proses nggawe aplikasi CRUD prasaja. Iki minangka bagean kapindho saka 4. Artikel kasebut utamane kanggo wong-wong sing wis ngrampungake 30-40 tingkat ing kene, nanging durung ngupayakake ngluwihi Jawa murni lan lagi wae diwiwiti (utawa bakal diwiwiti) kanggo mlebu ing jagad terbuka kanthi kabeh teknologi iki, frameworks lan tembung ora pati ngerti. Iki minangka bagean kapindho artikel "Introduction to Maven, Spring, MySQL, Hibernate and the first CRUD application." Bagean pisanan bisa dideleng kanthi ngetutake tautan iki: Pambuka kanggo Maven, Spring, MySQL, Hibernate lan aplikasi CRUD pisanan (bagean 1)

Isi:

Inggih, ayo nerusake, ayo saiki nyoba nggawe gudang kabeh film. Ing aplikasi cilik lan prasaja, mesthi, sampeyan bisa kanthi gampang nyelehake kabeh logika ing pengontrol, nanging, kaya sing wis kacathet, luwih becik langsung sinau carane nindakake kabeh kanthi bener. Mulane, ayo nggawe sawetara lapisan. Kita bakal duwe DAO tanggung jawab kanggo nggarap data, a Service , ngendi bakal ana kabeh limo logika liyane, lan Controller mung bakal proses panjalukan lan nelpon cara layanan perlu.

Obyek Akses Data

Data Access Object (DAO) minangka pola desain. Intine yaiku nggawe lapisan khusus sing mung tanggung jawab kanggo ngakses data (makarya karo database utawa mekanisme panyimpenan liyane). Ing paket kasebut, daokita bakal nggawe antarmuka FilmDAOsing bakal ana cara kayata nambah, mbusak, lsp. Aku disebut wong sethitik beda, nanging padha cocog karo operasi CRUD dhasar ( C reate, Read , U pdate, D elete).

Wigati dicathet ing kene, saliyane DAO, ana uga pendekatan kaya Repository, kayane meh padha, loro-lorone digunakake kanggo nggarap data. Aku durung ngerti apa fitur pendekatan iki lan apa bedane ing antarane. Mulane, aku bisa uga salah ing kene lan iki kudu diarani gudang, lan dudu Tao, utawa bisa uga ana ing antarane. Nanging ing pirang-pirang conto sing dakdeleng lan daksinaoni, iki diarani DAO, mula aku bakal ngarani padha. Ing wektu sing padha, mbok menawa ing endi wae ing teks aku bakal nggunakake tembung repositori. Menawi enten lepat, nyuwun pangapunten.

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);
}
Saiki kita butuh implementasine. Kita ora bakal nyambung database durung, iku isih sethitik medeni. Kanggo latihan lan digunakake, ayo simulasi panyimpenan ing memori lan nggawe dhaptar karo sawetara film. Kanggo nyimpen dhaptar, kita bakal nggunakake ora List, nanging Map, kanggo nggawe trep kanggo njupuk film tartamtu dening sawijining id, tanpa arep liwat kabeh dhaftar. Kanggo generasi idkita nggunakake AtomicInteger . Ayo nggawe kelas FilmDAOImpl, ngleksanakake kabeh cara lan isi peta. Mergo ngono.
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);
    }
}

Layanan

Saiki ayo nambah lapisan layanan. Ing asas, ing conto iki cukup bisa kanggo nindakake tanpa iku, matesi dhéwé kanggo DAO; aplikasi bakal banget prasaja lan ora ana rencana kanggo logika Komplek ing layanan. Nanging dumadakan ing mangsa ngarep sampeyan pengin nambah macem-macem komplikasi lan perkara sing menarik kanggo proyek kasebut, mula kanggo ngrampungake, ayo. Saiki, mung bakal nelpon metode saka DAO. serviceAyo nggawe antarmuka ing paket kasebut 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);
}
Lan implementasine:
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);
    }
}
Struktur proyek saiki katon kaya iki:
Pambuka kanggo Maven, Spring, MySQL, Hibernate lan aplikasi CRUD pisanan (bagean 2) - 1

Controller lan Views

Ayo saiki nggarap metode pengontrol lan ngisi kaca. Nalika ngisi kaca, kita butuh sawetara teknik. Contone, kanggo nampilake dhaptar film, kita butuh daur ulang, yen, ujar, kita pengin ngganti sawetara prasasti, gumantung saka paramèter, kita butuh kahanan, lsp. Format JSP (JavaServer Pages) ngidini sampeyan nggunakake sisipan kode java sing kabeh iki bisa ditindakake. Nanging aku ora pengin nggunakake kode java sing dicampur karo kode HTML ing kaca kasebut. Iku bakal, ing minimal, banget ala. Untunge, kanggo ngatasi masalah iki ana sing apik banget kaya JSTL (JavaServer Pages Standard Tag Library) utawa JSP Standard Tag Library. Iki ngidini kita nggunakake akeh tag tambahan ing kaca JSP kanggo macem-macem kabutuhan. Ayo disambungake menyang pom.xml:
<dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
</dependency>
Saiki ayo goleki controller. Kaping pisanan, ayo mbusak nggawe obyek saka ing kono Film, iki wis rampung kanggo testing lan kita ora perlu apa-apa liyane. Ayo nambah layanan ing kana lan nelpon metode kasebut.
public class FilmController {
    private FilmService filmService = new FilmServiceImpl();
Dadi, kita bakal nggawe metode kanggo saben kasus, nambah, mbusak, lsp. Cara pisanan kanggo nampilake kaca utama kanthi dhaptar film:
@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;
    }
Ora ana sing anyar ing kene. Kita entuk dhaptar film saka layanan kasebut lan ditambahake menyang model kasebut. Saiki ayo nggawe kaca utama films.jspsing cara iki ngasilake:
<%@ 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>
Ayo dideleng kanthi cetha ing kaca iki kanggo ndeleng apa. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - ing kene inti JSTL disambungake, sing kalebu tag utama kanggo nggawe siklus, kondisi, lsp .
  • <table>- tag kanggo nggawe tabel.
  • <tr>- baris meja
  • <th>- header kolom
  • <td>- sel meja
Pisanan, kita nggawe baris header tabel kanthi jeneng kolom. Banjur <c:forEach var="film" items="${filmsList}">, ing daur ulang (sing dijupuk saka inti JSTL), kita liwat kabeh unsur dhaftar liwati ( filmsList), kanggo saben unsur ( film) kita nggawe baris anyar lan nulis nilai sing cocog ing saben sel. Ana siji titik kene, rekaman misale jek film.idkudu dimangerteni minangka film.getId(), i.e. Lapangan ora diakses langsung, nanging getter diarani. Ing kolom pungkasan ( action) kita nggawe pranala kanggo mbusak lan nyunting (kita bakal nggawe cara sing cocog saiki). Inggih, ing ngisor iki link menyang cara kanggo nambah film anyar. Iki kaya apa: Sabanjure, ayo deleng cara sing bakal ngasilake kaca suntingan kanggo film tartamtu:
@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;
    }
Ana sing anyar katon ing kene - iki minangka anotasi @PathVariable. Iku nuduhake yen parameter iki ( int id) dijupuk saka baris alamat. Kanggo nunjukake lokasi parameter iki ing bilah alamat, konstruksi digunakake {id}(kanthi cara, yen jeneng variabel padha, kaya ing kasus iki, sampeyan ora kudu nuduhake ing kurung, nanging mung nulis. @PathVariable int id). Dadi, ing kaca utama kita wis nggawe tautan kanggo saben film sing nuduhake id:
<a href="/edit/${film.id}">edit</a>
Banjur nilai iki ditugasake kanggo parameter metode lan banjur digunakake kanggo njupuk film tartamtu saka gudang liwat layanan lan ditambahake menyang model. Iki minangka cara kanggo njupuk kaca panyuntingan, saiki kita butuh metode kanggo nyunting dhewe:
@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;
    }
Ing metode editPagekita nambahake atribut menyang model:
modelAndView.addObject("film", filmService.getById(id));
Lan saiki kanthi bantuan anotasi @ModelAttributekita entuk atribut iki lan kita bisa ngganti. Cara panyuwunan POSTamarga ing kene kita bakal ngliwati data kasebut. " redirect:/" tegese sawise nglakokake cara iki kita bakal dialihake menyang alamat " /", i.e. cara bakal mbukak allFilmslan kita bakal bali menyang kaca utama. Saiki ayo nggawe kaca dhewe 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>- formulir kanggo ngumpulake lan ngirim data, nuduhake sapa sing bakal ngolah ( /edit)
  • <input>- unsur antarmuka kanggo interaksi pangguna (tombol, kolom input, lsp.)
  • <label>- label teks
Dadi, nalika sampeyan ngeklik tombol kasebut, <input type="submit" value="Edit film">data saka formulir kasebut bakal dikirim menyang server (lapangan sing ora katon kanthi nilai wis ditambahake khusus idsupaya server ngerti cathetan ing database sing kudu dianyari). Ing metode kasebut editFilmbakal ditugasake menyang kolom atribut sing cocog film. Banjur kita bakal bali menyang kaca utama kanthi dhaptar sing dianyari. Kaca panyuntingan katon kaya mangkene: Saiki ayo miwiti nambahake film anyar menyang dhaptar. Kanggo nindakake iki, sampeyan uga butuh formulir kanggo ngetik lan ngirim data. Sampeyan bisa nggawe formulir ing kaca utama utawa sampeyan bisa nggawe kaca kapisah, kayata editPage.jsp. Nanging, ing tangan liyane, wangun kanggo nambah bakal persis padha kanggo editing, i.e. 4 kolom input lan tombol kirim. Dadi kenapa nggawe kaca anyar, ayo nggunakake editPage.jsp. Cara kanggo entuk kaca:
@RequestMapping(value = "/add", method = RequestMethod.GET)
    public ModelAndView addPage() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("editPage");
        return modelAndView;
    }
Ing metode kasebut, editPagekita uga ngliwati atribut kasebut supaya bisa diganti mengko, nanging ing kene kita mung nampa kaca kasebut. Lan cara kanggo nambah:
@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;
    }
Amarga kita ora ngliwati atribut ing kene, obyek anyar bakal digawe ing kene Film. Inggih, ora ana sing anyar ing kene. Iku uga worth kang lagi nyimak sing kita duwe loro cara kasedhiya ing " /add". Iki bisa ditindakake amarga dheweke nanggapi macem-macem jinis panjaluk. Kanthi ngetutake tautan ing kaca utama, kita njaluk panjaluk GET, sing ndadékaké kita menyang addPage. Lan nalika ing kaca nambah kita klik tombol kanggo ngirim data, request POST digawe, lan addFilm. Kanggo nambah film anyar, kita mutusake nggunakake kaca sing padha kanggo nyunting. Nanging ing kana data dikirim menyang alamat " /edit":
<c:url value="/edit" var="var"/>
<form action="${var}" method="POST">
    <input type="submit" value="Edit film">
</form>
Kita kudu ngapiki kaca supaya tumindak beda kanggo nambah lan nyunting. Kanggo ngatasi masalah iki, kita bakal nggunakake kondisi saka perpustakaan inti JSTL padha:
<%@ 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>
Sing. kita mung mriksa lapangan film.title. Yen kosong, banjur iku film anyar, kita kudu isi kabeh data kanggo lan ditambahake menyang dhaftar. Yen lapangan iki ora kosong, iku film saka dhaftar lan sampeyan mung kudu ngganti. Iku. kita entuk rong versi kaca: Ya, cara pengontrol pungkasan kanggo mbusak film saka dhaptar:
@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;
    }
Aku ora perlu komentar apa-apa ing kene, kabeh iki wis dianggep. Kita wis nggawe pranala menyang alamat iki ing kaca utama. Inggih, kabeh katon wis siyap ing kene, sampeyan bisa mbukak maneh lan ndeleng cara kerjane.

Repositori lan Layanan minangka Komponen Spring

Ayo nggawe koreksi cilik liyane. Kasunyatane saiki panyimpenan lan layanan mung kelas, lan supaya bisa digunakake, kita kudu nggawe obyek kelas dhewe ( new FilmServiceImpl()). Nanging kita duwe Spring disambungake kanthi alesan , supaya dheweke ngontrol masalah iki dhewe. Kanggo nyelehake kelas kita ing kontrol Spring, kita kudu nuduhake yen dheweke minangka komponen. Kanggo nindakake iki, kita menehi tandha kanthi anotasi khusus:
@Repository
public class FilmDAOImpl implements FilmDAO {
@Service
public class FilmServiceImpl implements FilmService {
Anotasi @Repositorylan @Service, uga @Controllerasalé saka @Component. Apa fitur tartamtu lan beda saka telung anotasi iki lan carane padha beda-beda saka komponen prasaja kudu diwaca kanthi kapisah ing dokumentasi utawa panuntun. Saiki, cukup ngerti manawa anotasi kasebut ngandhani Spring yen kelas kasebut minangka gudang lan layanan. Lan saiki kita ora perlu nggawe obyek konkrit saka kelas kasebut dhewe:
private FilmService filmService = new FilmServiceImpl();
Nanging, sampeyan bisa menehi tandha lapangan kanthi anotasi khusus lan Spring bakal milih implementasine sing cocog:
@Autowired
private FilmService filmService;
Anotasi @Autowired(otomatis naleni) ngandhani Spring sing kudu digali menyang konteks lan ngganti kacang cocok kene. Nyaman banget. Yen sadurunge nggunakake antarmuka supaya ora kuwatir babagan implementasine metode tartamtu, saiki kita ora perlu kuwatir babagan implementasine antarmuka kasebut dhewe lan malah ngerti jenenge. Gagasan kasebut ora dianjurake kanggo nggunakake ikatan otomatis ing lapangan, luwih becik nggunakake konstruktor utawa setter. Waca liyane babagan iki ing dokumentasi. Kanggo kita, ing prinsip, iki ora penting, kita bisa kanthi aman ninggalake kaya ngono. Nanging, amarga ide kasebut njaluk, kita bakal ngormati manawa kabeh iku apik lan tanpa peringatan kuning. Ing kelas controller, ayo nggawe setter lan anotasi:
@Controller
public class FilmController {

    private FilmService filmService;

    @Autowired
    public void setFilmService(FilmService filmService) {
        this.filmService = filmService;
    }
Lan uga kita nggawe setter kanggo FilmDAOing kelas FilmServiceImpl. Diterusake ... Ngenalake Maven, Spring, MySQL, Hibernate lan aplikasi CRUD pisanan (bagean 1) Ngenalake Maven, Spring, MySQL, Hibernate lan aplikasi CRUD pisanan (bagean 2) Ngenalake Maven, Spring, MySQL, Hibernate lan aplikasi CRUD pisanan (bagean 3) Pambuka kanggo Maven, Spring, MySQL, Hibernate lan aplikasi CRUD pisanan (bagean 4)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION