LoginSignup
41
41

More than 5 years have passed since last update.

コントローラからサービスを呼び出す。MVC揃える

Last updated at Posted at 2015-11-28

目的

コントローラからViewの表示を行うだけの状態から、

コントローラからサービスを呼び出し、
DB操作を行い、
結果をViewに返すまでの流れを実現するサンプルを作成する

環境

IDE STS
Spring Boot 1.3.0
Java 8
テンプレートエンジン Thymeleaf
Spring Data JPA
O/Rマッパー Hibernate

手順

前回の状態

前回のSpringBoot.png

・コントローラ
customersへマッピングされたlistメソッドを用意
customersへリクエストを受けると、
addAttributeメソッドにて"msg"に”サンプルメッセージ!”という文字列がひも付けられ、Viewに渡される。
viewは、resources/templates以下の、
test/test.htmlが呼び出される

CustomerController.java
package com.example.web;

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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.example.domain.Customer;
import com.example.service.CustomerService;

@Controller
@RequestMapping("customers")
public class CustomerController {
    @RequestMapping(method = RequestMethod.GET)
    public String list(Model model) {
        model.addAttribute("msg","サンプルメッセージ!");
        return "test/test";
    }
}

・テンプレート
html xmlns:th="http://www.thymeleaf.org"をヘッダにて呼び出し
th属性を使うための名前空間を指定する
th:text="${msg}"で、パラメータを取り出し、text型でセットする 文字列として表示される

test.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>top page</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
test
<p th:text="${msg}" /> 
</body>
</html>

・pom

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>webAppTest_version1.3</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>


今回の作業

スクリーンショット 2015-11-28 9.03.56.png

pomに以下の依存性を追加

pom.xml
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
</dependency>
<dependency>
  <groupId>org.lazyluke</groupId>
  <artifactId>log4jdbc-remix</artifactId>
  <version>0.2.7</version>
</dependency>
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.14.0</version>
  <scope>provided</scope>
</dependency>

サービスの追加

JPAクラスによるCLUD操作をcustomerRepository.findAll()等で実行している
このCLUD操作に関するメソッドは、customerRepositoryに実装されているのではなく、その継承元で定義されている。

CustomerService.java
package com.example.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.example.domain.Customer;
import com.example.repository.CustomerRepository;

@Service
@Transactional
public class CustomerService {
    @Autowired
    CustomerRepository customerRepository;

    public Customer save(Customer customer){
        return customerRepository.save(customer);
    }
    public List<Customer> findAll(){
        return customerRepository.findAll();
    }
    public Page<Customer> findAll(Pageable pageable){
        return customerRepository.findAllOrderByName(pageable);
    }
    public Customer findOne(Integer id){
        return customerRepository.findOne(id);
    }
    public Customer create(Customer custmer){
        return customerRepository.save(custmer);
    }
    public Customer update(Customer customer){
        return customerRepository.save(customer);
    }
    public void delete(Integer id){
        customerRepository.delete(id);
    }

}

DB操作

エンティティ

@EntityアノテーションでJPAエンティティであることを定義
@TableアノテーションでTable名とのひも付け
@Dataアノテーションにて、各フィールドのアクセッサ、toString equals hashCodeメソッドを生成する。(Lombok)
@NoArgsConstructor @AllArngConstructor コンストラクタを生成
@Id主キーを指定
@GeneratedValue 主キーをDBで自動採番する

Customer.java
package com.example.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "customers")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {
    @Id
    @GeneratedValue
    private Integer id;
    @Column(nullable = false)
    private String firstName;
    @Column(nullable = false)
    private String lastName;
}

repository

RDBMS操作を行う
JpaRepositoryクラスを継承したInterfaceを作成する
CLUDの基本的な操作はすでに定義されているため、Interfaceを定義するだけで
findOne
findAll
save
delete
メソッドが使える

@Queryアノテーションにより、JPQLによる処理も可能

CustomerRepository.java
package com.example.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.example.domain.Customer;

@Repository
@Transactional
public interface CustomerRepository extends JpaRepository<Customer, Integer>{

    @Query("SELECT x FROM Customer x ORDER BY x.firstName, x.lastName")
    Page<Customer> findAllOrderByName(Pageable pageable);

}

初期データの取り込み

resourceにsqlファイルを配置すると、実行前に実行してくれる。
DBの

data.sql
INSERT INTO customers(first_name, last_name) VALUES('中野', '西口');
INSERT INTO customers(first_name, last_name) VALUES('中野', '坂上');
INSERT INTO customers(first_name, last_name) VALUES('東', '中野');
INSERT INTO customers(first_name, last_name) VALUES('中野', '富士見町');

※そもそもDBの設定はどうなっているのか
h2を利用しているため、デフォルトの設定でインメモリで動いている。mysqlとかを利用する場合は設定ファイルが別途必要

Table定義は@Dataのエンティティから自動的に生成されている(
JPAによって)・・・のはず

上記のサービスをControllerから呼び出す

Controllerからサービスを呼び出し、結果をViewへ渡す

customerServiceのfindAll()メソッドから、検索を行う
addAttributeで"customers"というキーにcustomersオブジェクトをひもづける
テンプレートcustomers/listを表示する

CustomerController.java
package com.example.web;

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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.example.domain.Customer;
import com.example.service.CustomerService;

@Controller
@RequestMapping("customers")
public class CustomerController {

    @Autowired
    CustomerService customerService;

    @RequestMapping(method = RequestMethod.GET)
    String list(Model model) {
        List<Customer> customers = customerService.findAll();
        model.addAttribute("customers", customers);
        return "customers/list";
    }

    /*
    @RequestMapping(method = RequestMethod.GET)
    public String list(Model model) {
        model.addAttribute("msg","サンプルメッセージ!");
        return "customers/list";
    }
    */

}

Viewの表示

addAttrivuteで渡されたパラメータじゃ${customer}で取り出せる
もともとcustomerはList型で渡されていたため、
th:each にて繰り返し取得できる
customer:${customers}
にて、右のりすとからひとつづつcustomerオブジェクトを読み出し、列記できる

※Formの方は一旦表示だけまで

list.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>top page</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<table>
    <tr th:each="customer : ${customers}">
        <td th:text="${customer.id}"></td>
        <td th:text="${customer.lastName}"></td>
        <td th:text="${customer.firstName}"></td>
        <td>
            <from method="get">
                <input type="submit" name="from" value="編集" />
                <input type="hidden" name="id" th:value="${customer.id}" />
            </from>
        </td>
        <td>
            <from method="post">
                <input type="submit" value="削除" />
                <input type="hidden" value="id" th:value="${customer.id}" />
            </from>
        </td>
    </tr>
</table>

</body>
</html>


表示を確認

http://localhost:8080/test
よりブラウザで表示

スクリーンショット 2015-11-28 10.27.41.png

データが表示されました

参考文献

・[工学社はじめてのSpring Boot 第1版:槙俊明(平成27年1月10日)]
本書のSpring Bootは、バージョンが1.1.8.RELEASEを前提としていたため、
最新(僕の場合は1.3.0.RELEASE)のプロジェクトでそのままサンプルを実行すると正常に動かなかった。

一旦、別の情報をもとに1.3.0でThymeleafによるView表示を実現するところまでやった上で、サービスを1個づつ追記し、とりあえずこのようにしたら問題なく動いた。
(ただ、DBのログが出せていない。)
・Spring BootではじめるSpring MVCアプリケーション高速開発入門:http://libro.tuyano.com/index3?id=8486003&page=2

41
41
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
41