データのCRUD操作
以下のことを実施します。
1.CRUDを実装
2.sqlでデータをロードする
依存環境
・Spring Boot DevTools
・Lombok
・検証
・Spring Data JPA
・H2 Database
・Thymeleaf
・Spring Web
モデルの作成
以下のファイルを作成
package com.example.demo.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Size(max = 40)
private String name;
@ManyToOne
private Department department;
}
package com.example.demo.model;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Size(max = 40)
private String name;
@OneToMany(mappedBy = "department")
private List<Employee> employees;
}
リポジトリを作成
以下のファイルを作成
package com.example.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.model.Employee;
public interface EmployeeRepository extends JpaRepository<Employee,Long>{
}
package com.example.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.model.Department;
public interface DepartmentRepository extends JpaRepository<Department,Long>{
}
コントローラを作成
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
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 com.example.demo.model.Employee;
import com.example.demo.repository.EmployeeRepository;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Controller
public class EmployeeController {
private final EmployeeRepository repository;
@GetMapping("/")
public String showList(Model model) {
model.addAttribute("employees",repository.findAll());
return "index";
}
@GetMapping("/add")
public String addEmployee(@ModelAttribute Employee employee) {
return"form";
}
@PostMapping("/process")
public String process(@Validated @ModelAttribute Employee employee,BindingResult result) {
if(result.hasErrors()) {
return"form";
}
repository.save(employee);
return"redirect:/";
}
@GetMapping("/edit/{id}")
public String editEmployee(@PathVariable Long id,Model model) {
model.addAttribute("employee",repository.findById(id));
return"form";
}
@GetMapping("/delete/{id}")
public String deleteEmployee(@PathVariable Long id) {
repository.deleteById(id);
return"redirect:/";
}
}
pom.xmlを編集
dependencies内に以下を追加
<dependency>
<groupId>org.webjars</groupId>
<artifactId>startbootstrap-sb-admin-2</artifactId>
<version>4.0.6</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.40</version>
</dependency>
Thymeleafテンプレートを作成
トップページを作成
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:insert="fragments/base::header"></th:block>
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<th:block th:insert="fragments/sidebar :: sidebar"></th:block>
<!-- MAIN -->
<div id="content-wrapper" class="d-flex flex-column">
<div id="content">
<div class ="container-fluid">
<!-- DataTables -->
<div class="card shadow my-4">
<div class ="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">社員一覧</h6>
</div>
<div class="card-body">
<div class="table-reponsive">
<div th:if="${employees.size()==0}">該当データがありません</div>
<table class="table table-bordered"th:if="${employees.size()>0}">
<thead>
<tr>
<th>#</th>
<th>名前</th>
<th>部署名</th>
<th></th>
</tr>
</thead>
<tbody>
<tr th:each="employee:${employees}" th:object="${employee}">
<td th:text="*{id}"></td>
<td th:text="*{name}"></td>
<td th:text="*{department.name}"></td>
<td>
<a th:href="@{/edit/{id}(id=*{id})}" class="btn btn-primary btn-icon-split">
<span class="icon text-white-50">
<i class="fasfa-trash"></i>
</span>
<span class="text">編集</span>
</a>
<a th:href="@{/delete/{id}{id={*id})}" class="btn btn-danger btn-icon-split">
<span class="icon text-white-50">
<i class="fasfa-trash"></i>
</span>
<span class="text">削除</span>
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- End of Main -->
</div>
<th:blok th:insert="fragments/base :: scripts"></th:blok>
</body>
</html>
base.htmlを作成
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:fragment="header">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>社員情報アプリ</title>
<!-- These are required CSS -->
<link rel="stylesheet" th:href="@{/webjars/font-awesome/css/all.min.css">
<link rel="stylesheet" th:href="@{/webjars/startbootstrap-sb-admin-2/css/sb-admin-2.min.css}">
</th:block>
</head>
<body>
<!-- These are required JS -->
<th:block th:fragment="scripts">
<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
<script th:src="@{/webjars/popper.js/umd/popper.min.js}"></script>
<script th:src="@{/webjars/startbootstrap-sb-admin-2/js/sb-admin-2.min.js}"></script>
<script th:src="@{/webjars/chartjs/Chart.min.js}"></script>
</body>
</html>
sidebar.htmlを作成
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
</head>
<body>
<th:block th:fragment="sidebar">
<!-- Sidebar -->
<ul class="nabar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidbar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" th:href="@{/}">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-id-card"></i>
</div>
<div class="sidebar-brand-text mx-3">社員情報</div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item -->
<li class="nav-item active">
<a class="nav-link" th:href="@{/}">
<i class="fas fa-table"></i>
<span>社員一覧</span></a>
</li>
<li class="nav-item active">
<a class="nav-link" th:href="@{/add}">
<i class="fas fa-user-plus"></i>
<span>社員登録</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0"id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
</th:body>
</html>
社員登録ページ作成
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:insert="fragments/base :: header"></th:block>
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<th:block th:insert="fragments/sidebar :: sidebar"></th:block>
<!-- Main -->
<div id="content-wrapper" class="d-flex flex-column">
<div id="content">
<div class="container-fluid">
<!-- DataTales -->
<div class="card shadow my-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">社員登録</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<form th:action="@{/process}"th:object="${employee}"method="post">
<input type="hidden" th:field="*{id}">
<div class="form-group">
<label for="name">名前</label>
<input type="text" class="form-control"th:errorclass="is-invalid"th:field="*{name}">
<div class="invalid-feedback"th:errors="*{name}"></div>
</div>
<div class="form-group">
<label for="department">部署名</label>
<select class="form-control"th:field="*{department}">
<th:block th:each="department :${@departmentRepository.findAll()}">
<option th:value="${department.id}"th:text="${department.name}"></option>
</th:block>
</select>
</div>
<!-- Divider -->
<hr class="sidebar-divider my-4">
<button class="btn btn-primary btn-block col-md-4">
<i class="fas fa-editfa-fw"></i>
<span class="text">保存</span>
</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- End of Main -->
</div>
<th:block th:insert="fragments/base :: scripts"></th:block>
</body>
</html>
エラーページ作成
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:insert="fragments/base :: header"></th:block>
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<th:block th:insert="fragments/sidebar :: sidebar"></th:block>
<!-- Main -->
<div id="content-wrapper" class="d-flex align-items-center">
<div id="content">
<div class="container-fluid">
<!-- Error Text -->
<div class="text-center">
<div class="error mx-auto"th:attr="data-text=${status}"th:text="${status}">
<p class="text-gray-500 mb-0">ページを表示できません</p>
<a th:href="@{/}">←ホームに戻る</a>
</div>
</div>
</div>
</div>
<!-- End of Main -->
</div>
<th:block th:insert="fragments/base :: scripts"></th:block>
</div>
</body>
</html>
SQL作成
INSERT INTO department(name)
VALUES('営業'),('経理'),('開発'),('総務');
確認
ブラウザでhttp://localhost:8080/で開きトップページを確認
社員登録を押下後名前を入力、部署名を選択後保存ボタンを押下
社員登録一覧で登録されている状態で編集ボタンを押下し編集ができるか確認
社員一覧画面で保存している社員情報を削除ボタンを押下し削除されていることを確認
Iocコンテナを確認
以下のことを実施します。
1.LoCコンテナを確認
2.Scopeについて
依存関係
・Spring Boot DevTools
・Lombok
・検証
・Spring Data JPA
・H2 Database
・Thymeleaf
・Spring Web
アプリケーションクラスの編集
SpringlocAopApplication.javaを編集
package com.example.demo;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor
@SpringBootApplication
public class Sample74Application implements CommandLineRunner{
private final ApplicationContext appContext;
public static void main(String[] args) {
SpringApplication.run(Sample74Application.class, args);
}
@Override
public void run(String...args)throws Exception{
String[] allBeanNames = appContext.getBeanDefinitionNames();
for (String beanName:allBeanNames) {
log.info("Bean名:{}",beanName);
}
}
}
モデルの作成
package com.example.demo.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
public class Coffee {
@Id
@GeneratedValue
private Long id;
private String name;
}
リポジトリの作成
package com.example.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.model.Coffee;
public interface CoffeeRepository extends JpaRepository<Coffee,Long> {
}
コントローラを作成
package com.example.demo.controlle;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import com.example.demo.repository.CoffeeRepository;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Controller
public class HomeController {
private final ApplicationContext appContext;
@GetMapping("/")
public String showList(Model model) {
CoffeeRepository repository = (CoffeeRepository)appContext.getBean("coffeeRepository");
model.addAttribute("toString",this.toString());
model.addAttribute("allCoffee",repository.findAll());
return"index";
}
}
ScopeControllerを作成
package com.example.demo.controlle;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import com.example.demo.repository.CoffeeRepository;
import lombok.RequiredArgsConstructor;
@Scope("request")
@RequiredArgsConstructor
@Controller
public class ScopeController {
private final CoffeeRepository repository;
@GetMapping("/scope")
public String showList(Model model) {
model.addAttribute("toString",this.toString());
model.addAttribute("allCoffee",repository.findAll());
return"index";
}
}
SQL作成
CREATE TABLE coffee(
id BIGINT PRIMARY KEY,
name VARCHAR(60)
);
INSERT INTO coffee(id,name)
VALUES(1,'ブレンドコーヒー'),(2,'コーヒー');
確認
ブラウザでhttp://localhost:8080/で表示した場合、date.sqlのコーヒーを全て表示されていることを確認
ブラウザでhttp://localhost:8080/scopeで表示した場合でも同じように表示されていることを確認