Create a simple CRUD with SpringBoot + JPA + Thymeleaf ② ~ Screen and function creation ~

Contents

-Continued from Last time --Create a simple CRUD app with Spring Boot ――This time, create the following 4 screens and go through the processing --List screen --New screen

Functions to develop

  1. Create a player table to store player information
  2. Enable to operate the player table using JPA
  3. Creating an endpoint for player
  4. Create a template for each screen

1. Create a player table to store player information

--If you are using SpringBoot and JPA, creating an Entity class will automatically generate a table, so you don't have to hit SQL. --Create Player.java to save player information in src / main / java / com / example / baseball / domain

src/main/java/com/example/baseball/domain/Player.java


package com.example.baseball.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity // ①
public class Player {
    @Id // ②
    @GeneratedValue(strategy = GenerationType.IDENTITY) // ③
    private Long id;
    private String name;
    private Integer age;
    private String team;
    private String position;

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getTeam() {
        return team;
    }
    public void setTeam(String team) {
        this.team = team;
    }
    public String getPosition() {
        return position;
    }
    public void setPosition(String position) {
        this.position = position;
    }

    @Override
    public String toString() {
        return "Player [id=" + id + ", name=" + name + ", age=" + age + ", team=" + team + ", position=" + position + "]";
    }
}

-①: Link with DB table by adding @ Entity --②: The variable with @Id becomes the primer key of the table. --③: If you add @GeneratedValue, serial numbers will be assigned automatically.

2. Enable to operate the player table using JPA

--JPA provides the basic processing for accessing the table, so you don't have to write SQL. --Can be used by creating an interface that inherits JPA's JpaRepository --If you want to do something other than the typical operations such as findAll and save, you will need to add it to the repository. --Create PlayerRepository.java in src / main / java / com / example / baseball / repository

src/main/java/com/example/baseball/repository/PlayerRepository.java


package com.example.baseball.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.example.baseball.domain.Player;

@Repository
public interface PlayerRepository extends JpaRepository<Player, Long> {

}

--Create a service that calls the repository process --The business logic is written in service, and the repository is only DB access. --Call the service method when you want to perform processing that accesses the DB --Since there is no business logic at this stage, write only the process to call the repository method. --Create PlayerService.java in src / main / java / com / example / baseball / service

src/main/java/com/example/baseball/service/PlayerService.java


package com.example.baseball.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.baseball.domain.Player;
import com.example.baseball.repository.PlayerRepository;

@Service
public class PlayerService {
    // ①
    @Autowired
    private PlayerRepository playerRepository;

    public List<Player> findAll() {
        return playerRepository.findAll();
    }

    public Player findOne(Long id) {
        return playerRepository.findOne(id);
    }

    public Player save(Player player) {
        return playerRepository.save(player);
    }

    public void delete(Long id) {
        playerRepository.delete(id);
    }
}

--①: If you declare it with @Autowired, it will inject the bean, so you can use it without new.

3. Creating an endpoint for the player

--Create a method associated with the URL accessed by the user --The following 6 types of endpoints are created

HTTP method URL Controller method Overview
GET /players index() Display of list screen
POST /players create() Data storage
GET /players/new newPlayer() Display of new creation screen
GET /players/1/edit edit() Display of edit screen
GET /players/1 show() Display of reference screen
PUT /players/1 update() Data update
DELETE /players/1 destroy() Delete data

--Create PlayerController.java in src / main / java / com / example / baseball / controller

src/main/java/com/example/baseball/controller/PlayerController.java


package com.example.baseball.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.baseball.domain.Player;
import com.example.baseball.service.PlayerService;

@Controller
@RequestMapping("/players") // ①
public class PlayerController {
    @Autowired
    private PlayerService playerService;

    @GetMapping
    public String index(Model model) { // ②
        List<Player> players = playerService.findAll();
        model.addAttribute("players", players); // ③
        return "players/index"; // ④
    }

    @GetMapping("new")
    public String newPlayer(Model model) {
        return "players/new";
    }

    @GetMapping("{id}/edit")
    public String edit(@PathVariable Long id, Model model) { // ⑤
        Player player = playerService.findOne(id);
        model.addAttribute("player", player);
        return "players/edit";
    }

    @GetMapping("{id}")
    public String show(@PathVariable Long id, Model model) {
        Player player = playerService.findOne(id);
        model.addAttribute("player", player);
        return "players/show";
    }

    @PostMapping
    public String create(@ModelAttribute Player player) { // ⑥
        playerService.save(player);
        return "redirect:/players"; // ⑦
    }

    @PutMapping("{id}")
    public String update(@PathVariable Long id, @ModelAttribute Player player) {
        player.setId(id);
        playerService.save(player);
        return "redirect:/players";
    }

    @DeleteMapping("{id}")
    public String destroy(@PathVariable Long id) {
        playerService.delete(id);
        return "redirect:/players";
    }
}

--①: If you add @RequestMapping to the class, it will be applied to all the methods in the class. --That is, all the methods of this class are mapped to URLs starting with http: // localhost: 8080 / players --②: If you set a value of type Model in the argument of the method, an instance of Model will be passed automatically. --③: You can pass the value to the template by filling the model received in ② with the value. --Here, the list of players is set with the key name players. --④: Based on the returning character string, find the file under src / main / resources / templates / and return it to the user. --Here, src / main / resources / templates / players / index.html is returned. -⑤: You can get the value on the URL by setting @PathVariable in the method argument. --Here, when http: // localhost / players / 1 is accessed, 1 is entered in ʻid. --⑥: If you add @ModelAttributeto the method argument, you can get the body information of the sent request. --⑦: "redirect: / players" redirects to/ players --It feels like thehttp: // localhost: 8080 / players` is accessed without permission after the process of the create method is finished.

4. Create a template for each screen

--Since this time we will create a template for player, we will create it under src / main / resources / templates / players --Create the following 4 screen files --index.html (list screen) --new.html (new creation screen) --edit.html (edit screen) --show.html (reference screen)

Placement of static files

--Prepare css and javascript files before creating a template --This time, use Bootstrap --The latest version is 4 series, but this time we will use 3 series -Download from here and place the following files --Copy bootstrap.css in the css folder to the src / main / resources / static / css folder --Copy bootstrap.js in the js folder to the src / main / resources / static / js folder --Download and deploy jQuery on which Bootstrap depends --Download jQuery from here --If the source comes out directly, right-click and save it as a name --Place in the src / main / resources / static / js folder with the name jquery.js

スクリーンショット 2017-10-25 11.08.37.png

index.html

--Display a list of players in a table --Create ʻindex.html in src / main / resources / templates / players`

index.png

src/main/resources/templates/players/index.html


<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>Listing Players - baseball</title>
    <!-- ① -->
    <link rel="stylesheet" href="/css/bootstrap.css" />
    <script src="/js/jquery.js"></script>
    <script src="/js/bootstrap.js"></script>
  </head>
  <body>
    <div class="container">
      <h1>Listing Players</h1>
      <table class="table">
        <thead>
          <tr>
            <th>ID</th>
            <th>name</th>
            <th>age</th>
            <th>Team name</th>
            <th>Defensive position</th>
            <th></th>
            <th></th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          <!-- ② -->
          <tr th:each="player:${players}" th:object="${player}">
            <!-- ③ -->
            <td th:text="*{id}"></td>
            <td th:text="*{name}"></td>
            <td th:text="*{age}"></td>
            <td th:text="*{team}"></td>
            <td th:text="*{position}"></td>
            <!-- ④ -->
            <td><a class="btn btn-default btn-xs" th:href="@{/players/{id}(id=*{id})}">reference</a></td>
            <td><a class="btn btn-default btn-xs" th:href="@{/players/{id}/edit(id=*{id})}">Edit</a></td>
            <td>
              <!-- ⑤ -->
              <form th:action="@{/players/{id}(id=*{id})}" th:method="delete">
                <input class="btn btn-default btn-xs" type="submit" value="Delete" />
              </form>
            </td>
          </tr>
        </tbody>
      </table>
      <a class="btn btn-default" href="/players/new">Create New</a>
    </div>
  </body>
</html>

--①: Read css and javascript files --②: Loop processing is performed for the players passed from the Controller. --Loop processing can be described by doing something like th: each =" player: $ {players} " --In this example, the loop is looped by the number of players who are List, and each element in List is treated with the variable name player. --③: By setting th: object =" $ {player} ", you can abbreviate $ {player.xxx} as * {xxx} in the child element from this tag. Become --④: By setting th: href =" xxx ", the value set in the href attribute can be made dynamic. --The value where / players / {id} is set in the href attribute. Variables can be embedded in the {id} part, and the value is set by the subsequent (id = * {id}). --⑤: Since I want to access the delete process by setting the HTTP method to DELETE, I added th: method =" delete " to the form tag.

new.html

--Player new creation screen --Create new.html in src / main / resources / templates / players

new.png

src/main/resources/templates/players/new.html


<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>New Player - baseball</title>
    <link rel="stylesheet" href="/css/bootstrap.css" />
    <script src="/js/jquery.js"></script>
    <script src="/js/bootstrap.js"></script>
  </head>
  <body>
    <div class="container">
      <h1>New Player</h1>
      <form th:action="@{/players}" th:method="post">
        <div class="form-group">
          <label class="control-label">name</label>
          <input class="form-control" type="text" name="name" />
        </div>
        <div class="form-group">
          <label class="control-label">age</label>
          <input class="form-control" type="number" name="age" />
        </div>
        <div class="form-group">
          <label class="control-label">Team name</label>
          <input class="form-control" type="text" name="team" />
        </div>
        <div class="form-group">
          <label class="control-label">Defensive position</label>
          <input class="form-control" type="text" name="position" />
        </div>
        <button class="btn btn-default" type="submit">Create</button>
      </form>
      <div class="pull-right">
        <a class="btn btn-link" href="/players">To the list screen</a>
      </div>
    </div>
  </body>
</html>

edit.html

--Screen to edit the player whose id matches the value contained in the URL --Create ʻedit.html in src / main / resources / templates / players`

edit.png

src/main/resources/templates/players/edit.html


<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>Editing Player - baseball</title>
    <link rel="stylesheet" href="/css/bootstrap.css" />
    <script src="/js/jquery.js"></script>
    <script src="/js/bootstrap.js"></script>
  </head>
  <body>
    <div class="container">
      <h1>Editing Player</h1>
      <form th:action="@{/players/{id}(id=*{id})}" th:method="put" th:object="${player}">
        <div class="form-group">
          <label class="control-label">name</label>
          <!-- ① -->
          <input class="form-control" type="text" th:field="*{name}" />
        </div>
        <div class="form-group">
          <label class="control-label">age</label>
          <input class="form-control" type="number" th:field="*{age}" />
        </div>
        <div class="form-group">
          <label class="control-label">Team name</label>
          <input class="form-control" type="text" th:field="*{team}" />
        </div>
        <div class="form-group">
          <label class="control-label">Defensive position</label>
          <input class="form-control" type="text" th:field="*{position}" />
        </div>
        <button class="btn btn-default" type="submit">update</button>
      </form>
      <div class="pull-right">
        <a class="btn btn-link" href="/players">To the list screen</a>
      </div>
    </div>
  </body>
</html>

--①: For the value set in th: field, the variable name is set in the name attribute id attribute and the value is set in the value attribute. --If the value of * {age} is 20 as th: field =" * {age} ", name =" age "id =" age "value =" 20 " is automatically set. ing

show.html

--Screen to refer to player information whose id matches the value contained in the URL --Create show.html in src / main / resources / templates / players

show.png

src/main/resources/templates/players/show.html


<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>Show Player - baseball</title>
    <link rel="stylesheet" href="/css/bootstrap.css" />
    <script src="/js/jquery.js"></script>
    <script src="/js/bootstrap.js"></script>
  </head>
  <body>
    <div class="container">
      <h1>Show Player</h1>
      <div th:object="${player}">
        <div>
          <label>ID</label>
          <p th:text="*{id}"></p>
        </div>
        <div>
          <label>name</label>
          <p th:text="*{name}"></p>
        </div>
        <div>
          <label>age</label>
          <p th:text="*{age}"></p>
        </div>
        <div>
          <label>Team name</label>
          <p th:text="*{team}"></p>
        </div>
        <div>
          <label>Defensive position</label>
          <p th:text="*{position}"></p>
        </div>
      </div>
      <div>
        <a class="btn btn-default" th:href="@{/players/{id}/edit(id=*{id})}">Edit</a>
      </div>
      <div class="pull-right">
        <a class="btn btn-link" href="/players">To the list screen</a>
      </div>
    </div>
  </body>
</html>

Operation check

--So far, when you access http: // localhost: 8080 / players, the following functions are available.

demo3.gif

next time

--Continued here

Recommended Posts

Create a simple CRUD with SpringBoot + JPA + Thymeleaf ② ~ Screen and function creation ~
Create a simple CRUD with SpringBoot + JPA + Thymeleaf ③ ~ Add Validation ~
Create a simple CRUD with SpringBoot + JPA + Thymeleaf ④ ~ Customize error messages ~
Make a simple CRUD with SpringBoot + JPA + Thymeleaf ① ~ Hello World ~
Make a simple CRUD with SpringBoot + JPA + Thymeleaf ⑤ ~ Template standardization ~
Create a simple DRUD application with Java + SpringBoot + Gradle + thymeleaf (1)
[Rails withdrawal] Create a simple withdrawal function with rails
Draw screen with Thymeleaf in SpringBoot
Create a simple web application with Dropwizard
Create a simple on-demand batch with Spring Batch
Create a simple bar chart with MPAndroidChart
Create a simple bulletin board with Java + MySQL
04. I made a front end with SpringBoot + Thymeleaf
Create CRUD apps with Spring Boot 2 + Thymeleaf + MyBatis
Show a simple Hello World with SpringBoot + IntelliJ
A simple rock-paper-scissors game with JavaFX and SceneBuilder
Try searching for a zip code with REST API using SpringBoot, H2 DB and JPA REST-Only 3 classes to create-
A simple CRUD app made with Nuxt / Laravel (Docker)
Create an EC site with Rails 5 ⑨ ~ Create a cart function ~
Create a simple demo site with Spring Security with Spring Boot 2.1
Create a login authentication screen using the session function
Create a blog with Jekyll and GitHub Pages @ Theme setting
I wrote a CRUD test with SpringBoot + MyBatis + DBUnit (Part 1)
I want to make a function with kotlin and java!
Create a blog with Jekyll and GitHub Pages @ Initial Settings
Connect to database with spring boot + spring jpa and CRUD operation
A Simple CRUD Sample Using Java Servlet / JSP and MySQL
Create a playground with Xcode 12
Create a name input function
Create a simple web server with the Java standard library com.sun.net.httpserver
Create a JVM for app distribution with JDK9 modules and jlink
[Swift] Create a project with Xcode (ver 12.1) and display "Hello, World!"
Create a high-performance enum with fields and methods like Java with JavaScript
Create a flyway jar with maven and docker build (migrate) with docker-maven-plugin
Let's create a parameter polymorphic mechanism with Generic Dao and Hibernate