目次
はじめに
Javaの人気フレームワーク「Spring Boot」と「Spring Boot」と相性の良いテンプレートエンジン「Thymeleaf」を使用して登録画面を作成する方法を紹介します。
また、データベースへの登録はJPAを使用しています。
スポンサーリンク
本記事で作成する画面のイメージは以下の通り。
「キャンセル」リンクまたは「登録」ボタン押下で一覧画面に戻るようにします。
一覧画面については「Spring Boot + Thymeleafで一覧画面を作成する」の記事を参照してください。
[テーブル定義]
物理名 | 論理名 | データ型 | NOT NULL | 説明 |
id | ID | BIGINT(20) | 〇 | 主キー(AUTO_INCREMENT) |
name | 名前 | VARCHAR(100) | 〇 | ユーザーの名前 |
address | 住所 | VARCHAR(255) | ユーザーの住所 | |
phone | 電話番号 | VARCHAR(50) | ユーザーの電話番号 | |
update_date | 更新日時 | DATETIME | 〇 | 最終更新日時 |
create_date | 更新日時 | DATETIME | 〇 | 登録日時 |
delete_date | 更新日時 | DATETIME | 論理削除した日時 |
バックエンド(サーバー)側のソースコード
コントローラークラス(UserController.java)
「displayAdd」メソッドで登録画面に表示するオブジェクトを返却し登録画面を表示
登録画面から「登録」ボタンを押下された時に「create」メソッドが動き出し、入力チェックとデータ登録処理を行っています。
package com.example.demo.controller; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.ObjectError; 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.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.example.demo.dto.UserRequest; import com.example.demo.entity.User; import com.example.demo.service.UserService; /** * ユーザー情報 Controller */ @Controller public class UserController { /** * ユーザー情報 Service */ @Autowired UserService userService; /** * ユーザー情報一覧画面を表示 * @param model Model * @return ユーザー情報一覧画面 */ @GetMapping(value = "/user/list") public String displayList(Model model) { List<User> userlist = userService.searchAll(); model.addAttribute("userlist", userlist); return "user/list"; } /** * ユーザー新規登録画面を表示 * @param model Model * @return ユーザー情報一覧画面 */ @GetMapping(value = "/user/add") public String displayAdd(Model model) { model.addAttribute("userRequest", new UserRequest()); return "user/add"; } /** * ユーザー新規登録 * @param userRequest リクエストデータ * @param model Model * @return ユーザー情報一覧画面 */ @RequestMapping(value = "/user/create", method = RequestMethod.POST) public String create(@Validated @ModelAttribute UserRequest userRequest, BindingResult result, Model model) { if (result.hasErrors()) { List<String> errorList = new ArrayList<String>(); for (ObjectError error : result.getAllErrors()) { errorList.add(error.getDefaultMessage()); } model.addAttribute("validationError", errorList); return "user/add"; } // ユーザー情報の登録 userService.create(userRequest); return "redirect:/user/list"; } }
サービスクラス(UserService.java)
データベース接続はJPA、トランザクション管理は@Transactionalのアノテーションを使用しています。@Transactionalを使う事で「create」メソッドの登録に成功すればコミット、失敗してExceptionが発生すればロールバックを自動で行ってくれます。
ただ@Transactionalは、非検査例外(RuntimeException及びそのサブクラス)が発生した場合はロールバックされるが、検査例外(Exception及びそのサブクラス)が発生した場合はロールバックされずコミットされるので、「@Transactional(rollbackOn = Exception.class)」と定義することで、検査例外もロールバックされるようにしています。
package com.example.demo.service; import java.util.Date; import java.util.List; import javax.transaction.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.example.demo.dto.UserRequest; import com.example.demo.entity.User; import com.example.demo.repository.UserRepository; /** * ユーザー情報 Service */ @Service @Transactional(rollbackOn = Exception.class) public class UserService { /** * ユーザー情報 Repository */ @Autowired private UserRepository userRepository; /** * ユーザー情報 全検索 * @return 検索結果 */ public List<User> searchAll() { return userRepository.findAll(); } /** * ユーザー情報 新規登録 * @param user ユーザー情報 */ public void create(UserRequest userRequest) { Date now = new Date(); User user = new User(); user.setName(userRequest.getName()); user.setAddress(userRequest.getAddress()); user.setPhone(userRequest.getPhone()); user.setCreateDate(now); user.setUpdateDate(now); userRepository.save(user); } }
エンティティクラス(User.java)
データベースから取得したデータを格納するエンティティクラスの内容は以下の通り。@Dataアノテーションを使用して、getter、setterの定義を省略しています。
package com.example.demo.entity; import java.io.Serializable; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import lombok.Data; /** * ユーザー情報 Entity */ @Entity @Data @Table(name="user") public class User implements Serializable { /** * ID */ @Id @Column(name="id") @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; /** * 名前 */ @Column(name="name") private String name; /** * 住所 */ @Column(name="address") private String address; /** * 電話番号 */ @Column(name="phone") private String phone; /** * 更新日時 */ @Column(name="update_date") private Date updateDate; /** * 登録日時 */ @Column(name="create_date") private Date createDate; /** * 削除日時 */ @Column(name="delete_date") private Date deleteDate; }
リポジトリクラス(UserRepository.java)
データベースにアクセスする為のリポジトリクラスの内容は以下の通り。
package com.example.demo.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import com.example.demo.entity.User; /** * ユーザー情報 Repository */ @Repository public interface UserRepository extends JpaRepository<User, Long> {}
スポンサーリンク
Data Transfer Object(UserRequest.java)
登録画面からのリクエストデータを格納するオブジェクトクラスは以下の通り。
入力チェックは「Bean Validation」を使用しています。@NotEmptyや@Sizeなどを定義することで簡単に入力チェックを実装することができます。
package com.example.demo.dto; import java.io.Serializable; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import lombok.Data; /** * ユーザー情報 リクエストデータ */ @Data public class UserRequest implements Serializable { /** * 名前 */ @NotEmpty(message = "名前を入力してください") @Size(max = 100, message = "名前は100桁以内で入力してください") private String name; /** * 住所 */ @Size(max = 255, message = "住所は255桁以内で入力してください") private String address; /** * 電話番号 */ @Pattern(regexp = "0\d{1,4}-\d{1,4}-\d{4}", message = "電話番号の形式で入力してください") private String phone; }
フロントエンド(クライアント)側のソースコード
HTML(add.html)
以下が登録画面のHTMLです。入力チェックエラーが発生した場合は、画面上部へエラー内容を表示するようにしています。
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <title>ユーザー新規登録</title> <link href="/css/add.css" rel="stylesheet"></link> <meta charset="utf-8" /> </head> <body> <table> <tr th:if="${validationError}" th:each="error : ${validationError}"> <td style="color:red;" th:text="${error}"></td> </tr> </table> <h1>ユーザー新規登録</h1> <form th:action="@{/user/create}" th:object="${userRequest}" th:method="post"> <a href="/user/list">キャンセル</a> <table> <tr> <th class="cell_title">名前</th> <th class="cell_required">※</th> <td><input type="text" th:field="*{name}"></td> </tr> <tr> <th class="cell_title">住所</th> <th class="cell_required"></th> <td><input type="text" th:field="*{address}"></td> </tr> <tr> <th class="cell_title">電話番号</th> <th class="cell_required">※</th> <td><input type="text" th:field="*{phone}"></td> </tr> </table> <div class="btn_area_center"><input type="submit" value="登録" class="btn"></div> </form> </body> </html>
スタイルシート(add.css)
body { width: 80%; } table{ width: 100%; border-collapse: collapse; font-size: 13px; } table th, table td { border: 1px solid #ddd; padding: 6px; } table th { background-color: #F2F2F2; } table input { width:90%; } .cell_title { border-right: 0; } .cell_required{ color: red; font-size: 12px; width: 10px; border-left: 0; } .btn { width: 100px; text-align: center; } .btn_area_center { margin-top: 20px; text-align: center; }
動作確認
Spring Bootプロジェクトを実行して http://localhost:8080/user/add へアクセスします。
登録画面が表示されます。データを入力し登録が完了できれば完成です。