プロジェクトの準備
Spring Bootのプロジェクトの用意ができていない方は以下を参考にプロジェクトを作成する。
Macの方はMySQLの準備は以下の記事を参考にする。

クラス作成・コード記述
srcフォルダー以下のファイル構造は以下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
spring-boot-mysql (master) ✔ tree src src ├── main │ ├── java │ │ └── com │ │ └── example │ │ └── springbootmysql │ │ ├── HelloApi.java │ │ ├── SpringBootMysqlApplication.java │ │ ├── controller │ │ │ └── BookController.java │ │ ├── model │ │ │ └── Book.java │ │ ├── repository │ │ │ └── BookRepository.java │ │ └── service │ │ └── BookService.java │ └── resources │ └── application.yml └── test └── java └── com └── example └── springbootmysql └── SpringBootMysqlApplicationTests.java |
APIへのリクエストをハンドリングするcontroller層、ビジネスロジックを管理するservice層、データソースにアクセスするrepository層という感じでパッケージを分けています。
build.gradleにはMySQLを扱うためにdependenciesに以下を追加。
1 2 3 4 5 6 7 8 9 |
// 以下はmysqlを扱うために必要 compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa' runtimeOnly 'mysql:mysql-connector-java' // 以下のlombokはwebももし入ってなかったら入れる implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok:1.18.10' annotationProcessor 'org.projectlombok:lombok:1.18.10' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' |
以下からは各クラスファイルの記述内容です。
Book.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
package com.example.springbootmysql.model; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.*; import java.io.Serializable; /* * delete_flag=0(false)のものだけ取り出したかったら@Whereでしていできる * */ @Data @AllArgsConstructor @NoArgsConstructor @Entity public class Book implements Serializable{ /* * テーブルのIDカラム * */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer bookId; /* * 値の検証をしたければ以下のようなアノテーションをつけるとよい * @NotNull : nullはダメ * @Column(nullable = false, unique = ture) : nullはダメ、重複する値はダメ * @Pattern(regexp = "", message = "") : 受け取る文字列の正規表現 * @Size(max = , min = ) : 受け取る値の最大値最小値 * */ private String title; private String description; @Column(nullable = false, columnDefinition = "tinyint(1) default 0") private boolean deleteFlag; } |
MySQLのテーブル定義を書いたクラス。@EntityとつけることでMySQLのレコードデータとして扱えるようになる。クラス名がテーブル名と一致しない場合は@Table(name = “テーブル名”)をつけることで対応させることができる。
booleanでデフォルト値を扱う場合は@Column(nullable = false, columnDefinition = "tinyint(1) default 0")
と書くことでboolean型を扱えるようになる。(0がfalse)
BookController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package com.example.springbootmysql.controller; import com.example.springbootmysql.model.Book; import com.example.springbootmysql.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/book") public class BookController { @Autowired BookService bookService; @RequestMapping(method = RequestMethod.GET, path = "/") public ResponseEntity<List<Book>> getBooks() { return new ResponseEntity<>(bookService.getBooks(), HttpStatus.OK); } @RequestMapping(method = RequestMethod.GET, path = "/{bookId}") public ResponseEntity<Book> getBook(@PathVariable(value = "bookId") int bookId) { return new ResponseEntity<>(bookService.getBook(bookId), HttpStatus.OK); } @RequestMapping(method = RequestMethod.POST, path = "/") public ResponseEntity<Integer> addBook(@RequestBody Book book) { return new ResponseEntity<>(bookService.addBook(book), HttpStatus.CREATED); } } |
@RestControllerでこのクラスがRESTAPIとして使えるようにする。
@RequestMapping(“/book”)をつけることで、http(s)://<domain>/bookの形でAPIにアクセスできるようになる。
@AutowiredとつけることでbookServiceをDIしている。
@RequestMapping(method = RequestMethod.GET, path = “/”)でこのメソッドを実行する為のRESTAPIのメソッド、URLパスを定義できる。pathの値を{}で囲ったものはURLパラメータとして受け取れ、メソッドの引数に値が入る。
@PathVariable(value = “bookId”)でメソッドがどのRequestMappingのURLパラメータを受け取るか定義できる。
@RequestBodyはPOSTメソッドでリクエストボディを受け取る為のクラスにつける。本来はリクエストボディ用のクラスとMySQL用のクラスは分けるべきだがここでは同じにしている。
BookService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.example.springbootmysql.service; import com.example.springbootmysql.model.Book; import com.example.springbootmysql.repository.BookRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class BookService { @Autowired BookRepository bookRepository; public List<Book> getBooks() { Book book = new Book(); return bookRepository.findAll(); } public Book getBook(int bookId) { return bookRepository.findByBookId(bookId); } public int addBook(Book book) { return bookRepository.save(book).getBookId(); } } |
@ServiceでこのクラスがビジネスロジックをもつDIクラスということを示す。@Componentでも挙動は同じだが、クラスの役割としてわかりやすいように@Serviceにする。
様々なデータソースを参照したり、計算したりするときはこのクラスのメソッドに書く。
BookRepository.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.example.springbootmysql.repository; import com.example.springbootmysql.model.Book; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import javax.transaction.Transactional; import java.util.List; @Repository public interface BookRepository extends JpaRepository<Book, Integer> { // 以下と同じ // @Query(nativeQuery = true, value = "select * from book") // List<Book> findAllBooks(); @Override List<Book> findAll(); // 以下と同じ // @Query(nativeQuery = true, value = "select * from book b where b.book_id = ?1") // Book findBook(int id); Book findByBookId(Integer id); @Override @Transactional Book save(Book book); } |
@Repositoryをつけることでこのクラスがデータソースを扱うクラスということを示す。今回はJPAを使ってMySQLにアクセスしているのでJpaRepositoryをextendsしている。メソッドめいとJPAのルールに従って書くことでSQLを直接書かなくてもMySQLの操作ができる
JpaRepository<Book, Integer>とすることで、テーブルの構造に対応するクラスはBookで、テーブルのIDがint型であることを示す。
List<Book> findAll();テーブルから全レコード取る為のメソッドである。findAllがJpaRepositoryにあるのでそのまま受け取るクラスだけ指定して使っている。これは以下のように書くのと同じである。@Queryを使うことでこのメソッドが呼ばれた時に実行するSQLを直接記述することができる。
1 2 |
@Query(nativeQuery = true, value = "select * from book") List<Book> findAllBooks(); |
Book findByBookId(Integer id);はIDを指定して1レコードだけ取得するためのメソッドである。こちらは以下のように書くのと同じである。?1と書くことでメソッドの引数に対応した順番で値を参照することができる。
1 2 |
@Query(nativeQuery = true, value = "select * from book b where b.book_id = ?1") Book findBook(int id); |
レコードを作成、更新するときは@Transactionalとつけることでトランザクション管理がその処理に対してできるようになる。
application.yml(application.propatiesより記述しやすいのでapplication.ymlを作っている)
1 2 3 4 5 6 7 8 9 10 |
spring: datasource: url: jdbc:mysql://localhost:3306/store username: root password: パスワード driverClassName: com.mysql.jdbc.Driver jpa: database: MYSQL hibernate: ddl-auto: update |
urlはjdbc:mysql://<ドメイン>:<ポート番号>/<データベース名>で書く。ddl-auto: updateとすることで起動時にテーブルがなかったら自動でEntiryクラスを参照しその定義にあったテーブルを作ってくれる。(普通はSQLでcreate tableでテーブルを作るが今回は簡略化のためddl-autoを使う。)
あとはプロジェクトを起動して以下のコマンドを叩けばデータの作成、取得ができているのが確認できます。
1 2 3 4 5 6 7 8 |
# add book curl -X POST -H "Content-Type: application/json" -d '{"title":"kimetsu", "description":"kimetsu"}' localhost:8080/book/ # select all books curl localhost:8080/book # select one book by id curl localhost:8080/book/1 |
コメント
[…] Spring BootとJPAでMySQLに繋ぐ – データの取得と作成プロジェクトの準備Spring Bo… […]
[…] Spring BootとJPAでMySQLに繋ぐ – データの取得と作成プロジェクトの準備Spring Bo… […]
[…] Spring BootとJPAでMySQLに繋ぐ – データの取得と作成プロジェクトの準備Spring Bo… […]