Hello, JPA

Spring Boot JPAを使って見ました。
データベースの構築はメンドウなので組み込み型のH2DBを利用します。

[広告]
[広告]

Hello, Thymeleafからの変更概要

src
├─main
│  ├─groovy
│  │  └─sample
│  │      │  Application.groovy
│  │      │  
│  │      ├─app
│  │      │  └─product
│  │      │          ProductController.groovy  // 変更
│  │      │          
│  │      ├─domain
│  │      │  └─model
│  │      │          Product.groovy            // 新規作成
│  │      │          
│  │      └─repository
│  │              ProductRepository.groovy      // 新規作成
│  │              
│  ├─java
│  └─resources
│      │  application.properties                // 新規作成
│      │  data.sql                              // 新規作成
│      │  
│      └─templates
│          └─product
│                  index.html                    // 変更
│                  
└─test
    ├─groovy
    ├─java
    └─resources

build.gradle

・dependenciesに追加
dependencies {
    compile('org.codehaus.groovy:groovy:2.4.12')

    compile('org.springframework.boot:spring-boot-starter-web')
    providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
    testCompile('org.springframework.boot:spring-boot-starter-test')
    compile 'org.springframework.boot:spring-boot-starter-thymeleaf'
    
    // 以下を追加
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('com.h2database:h2:1.4.196')
}

H2とJPAの設定

・resources/application.propertiesを作成
# H2の設定
spring.datasource.url=jdbc:h2:mem:TEST_DB;DB_CLOSE_ON_EXIT=TRUE
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=
spring.datasource.password=
spring.datasource.sql-script-encoding=UTF-8

# JPAの設定
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop

・spring.jpa.hibernate.ddl-autoは次の設定があります
create-drop テーブルを削除して再作成。データは消える。モデル構造が変わる開発中に便利。
none 何もしない。本番用の設定。
※他にもcreate, update, validateとあるけど使ったことないですねー。

モデルを作成

・sample.domain.model.Productを作成
package sample.domain.model

import org.hibernate.validator.constraints.NotEmpty
import javax.persistence.*
import javax.validation.constraints.NotNull

@Entity
class Product {
    // 自動生成するPK
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long id

    @NotEmpty
    String name

    @NotNull
    Integer price
}
・hibernateをcreate-dropにしているので、spring-boot起動時にproductテーブルを自動生成します。

Repository定義を作成

・interfaceを作成します。
package sample.domain.repository

import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
import sample.domain.model.Product

@Repository
interface ProductRepository extends JpaRepository {
}
・今回利用するメソッドはJpaRepositoryに定義済みなので、中身は空です。
・interface定義だけでいいの?と思いますが、JPAの命名規約にそったメソッドは自動実装されます

data.sqlの作成

・spring boot起動時にproductテーブルに初期データを登録するために作成します。
・resources/data.sql
insert into product(name, price) values ('商品A', 100);
insert into product(name, price) values ('商品B', 200);
insert into product(name, price) values ('商品C', 300);
insert into product(name, price) values ('商品D', 400);
insert into product(name, price) values ('商品E', 500);
・application.propertiesで次のエンコード設定を入れないと文字化けするので注意が必要です。
spring.datasource.sql-script-encoding=UTF-8
・また本番環境でdata.sqlが実行されると悲惨なことになるため、war化する際に抜いておくのが望ましいですね

ProductControllerの変更

以前作成したProductControllerを次のように書き換えます。
package sample.app.product

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.servlet.ModelAndView
import sample.domain.repository.ProductRepository

@Controller
@RequestMapping("product")
class ProductController {
    // (1)
    @Autowired
    ProductRepository productRepo

    @RequestMapping(value="index", method=RequestMethod.GET)
    ModelAndView index() {
        ModelAndView mv = new ModelAndView()

        // (2)
        List productList = productRepo.findAll()

        // (3)
        mv.viewName = "product/index"

        // (4)
        mv.addObject("productList", productList)

        return mv
    }
}
・(1) ControllerでRepositoryにアクセスすべきでないと考えていますが、説明を簡潔にするためDIします。
 ※ServiceでDIするのが望ましいと考えています。
・(2) findAll()メソッドを使用し、productテーブルから全件取得します。
・(3) resources/templates/product/index.htmlを呼び出すよう設定します。
・(4) productテーブルのレコードリストをThymeleafで利用できるよう設定

product/index.htmlの変更

以前作成したresources/templates/product/index.htmlを次のように書き換えます。
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
</head>
    <body>
    <div th:each="product : ${productList}">
        <span th:text="${product.name}"></span>
        <span th:text="${product.price}"></span>
    </div>
    </body>
</html>

実行結果

     

コメントを残す

メールアドレスが公開されることはありません。