quarkusを使う(mybatis編)

こんばんは、エキサイト株式会社の中尾です。

前回の続きです。 mybatisを入れていきます。 mybatisにはserviceと同様@Singletonをつけて、@Injectで呼び出します。 その際、repositoryを間に挟みます。

まず、必要なextentionをgradleに追加します。

implementation 'io.quarkiverse.mybatis:quarkus-mybatis:0.0.10'
implementation 'io.quarkus:quarkus-jdbc-mysql:0.26.1'

続いてデータベースの設定です。

CREATE schema test;

CREATE TABLE book (
    id integer not null primary key,
    title varchar(80) not null,
    author varchar(80) not null,
    created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO `test`.`book` (`id`, `title`, `author`) VALUES (1, 'hobby', 's-nakao');

続いてアプリケーションの設定です、

  • application.properties
quarkus.datasource.db-kind=mysql
quarkus.datasource.username=YYYYYYY
quarkus.datasource.password=XXXXXXX
quarkus.datasource.jdbc.url=jdbc:mysql://localhost/test

※サンプルです。

  • repository interface
package org.my.hobby.repository;

import org.my.hobby.core.Book;

public interface BookRepository {
    Book find(String title);
}
  • repository impl
package org.my.hobby.repository;

import javax.inject.Inject;
import javax.inject.Singleton;

import java.util.Optional;

import org.my.hobby.core.Book;
import org.my.hobby.persistence.BookDto;
import org.my.hobby.persistence.BookMapper;

@Singleton
public class BookRepositoryImpl implements BookRepository {

    @Inject
    BookMapper bookMapper;

    @Override
    public Book find(String title) {
        final Optional<BookDto> book = bookMapper.getBook(title);
        return book
                .map(bookDto -> new Book(bookDto.getTitle(), bookDto.getAuthor()))
                .orElse(new Book("", ""));
    }
}
  • persistence interface

テキストブロック使います。 簡単なselectでも私はsql書きたい人です。 persistenceに全てのSQLをできるだけ書きたいです。

package org.my.hobby.persistence;

import java.util.Optional;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface BookMapper {
    @Select("""
        SELECT
            id,
            title,
            author,
            created
        FROM
            book
        WHERE
            title = #{title}
    """)
    Optional<BookDto> getBook(String title);
}
  • persistence dto
package org.my.hobby.persistence;

import java.time.LocalDateTime;

public class BookDto{
    private Integer id;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public LocalDateTime getCreated() {
        return created;
    }

    public void setCreated(LocalDateTime created) {
        this.created = created;
    }

    private String title;
    private String author;
    private LocalDateTime created;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
}
  • service impl

シンプルになります。

package org.my.hobby.service;

import javax.inject.Inject;
import javax.inject.Singleton;

import org.my.hobby.core.Book;
import org.my.hobby.repository.BookRepository;

@Singleton
public class BookServiceImpl implements BookService {

    @Inject
    BookRepository bookRepository;

    @Override
    public Book find(String title) {
        return bookRepository.find(title);
    }
}
  • コントローラー

前回のコントローラーは変わりません。

package org.my.hobby;

import javax.inject.Inject;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.constraints.NotBlank;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.Set;
import java.util.stream.Collectors;

import org.my.hobby.core.Book;
import org.my.hobby.service.BookService;

record BookSearchRequest(
        @NotBlank(message = "Title may not be blank") String title) {
}

record BookSearchResponse(
        boolean success,
        String message,
        Book book) {
    record Book(String title, String author) {
    }
}

@Path("/book/search")
public class BookController {

    @Inject
    Validator validator;

    @Inject
    BookService bookService;

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public BookSearchResponse search(BookSearchRequest bookSearchRequest) {
        Set<ConstraintViolation<BookSearchRequest>> violations = validator.validate(bookSearchRequest);
        if (!violations.isEmpty()) {
            final String errorMessage = violations
                    .stream()
                    .map(e -> e.getMessage())
                    .collect(Collectors.joining(","));
            final BookSearchResponse.Book hobbyBook = new BookSearchResponse.Book("", "");
            return new BookSearchResponse(false, errorMessage, hobbyBook);
        }

        final Book book = bookService.find(bookSearchRequest.title());
        final BookSearchResponse.Book hobbyBook = new BookSearchResponse.Book(book.title(), book.author());
        return new BookSearchResponse(book.isFind(), book.message(), hobbyBook);
    }
}
  • curlでアクセス
shogo.nakao@localhost:(App-Db-Blog-Fan) $ curl --location --request POST 'http://localhost:8080/book/search' \
--header 'Content-Type: application/json' \
--data-raw '{
        "title": "hobby"
}'

{"success":true,"message":"","book":{"title":"hobby","author":"s-nakao"}}%
shogo.nakao@localhost:(App-Db-Blog-Fan) $ curl --location --request POST 'http://localhost:8080/book/search' \
--header 'Content-Type: application/json' \
--data-raw '{
        "title": "s-nakao"
}'

{"success":false,"message":"not found book","book":{"title":"","author":""}}%
shogo.nakao@localhost:(App-Db-Blog-Fan) $ curl --location --request POST 'http://localhost:8080/book/search' \
--header 'Content-Type: application/json' \
--data-raw '{
}'

{"success":false,"message":"Title may not be blank","book":{"title":"","author":""}}%

取得できました!よかったですね!

一通り、controller,servie,repositoryができました。簡単でしたね。

quarkusでmybatisの設定は以下を参考にしてください。

Quarkus - Using MyBatis :: Quarkiverse Documentation

最後に、弊社では採用もバシバシ実施しているので興味のあるかたがいましたらご応募ください。

www.wantedly.com



Advent Calendar 2021を引き続き楽しんでいただけると嬉しいです。

qiita.com