본문 바로가기
Web Programming/springboot

VSCode에서 Spring boot + JPA(mysql) on Windows 10 + Docker 튜토리얼

by 맑은안개 2021. 10. 20.

Spring boot + JPA(mysql) on Windows 10 + Docker

1. 개요

이번 블로그에서는 Spring Boot를 사용하여 간단하게 JPA를 사용해본다. JPA datasource는 Mysql 8.0.26 ( 블로그 작성일 기준 최신 )을 사용하고 에디터는 VSCode를 사용한다.

Mysql은 Docker 컨테이너에서 기동한다. Docker 환경을 패스한다면 로컬에 mysql이 설치되어 있거나, Spring-boot-starter-data-jpa의 default DB인 h2 를 사용해도 좋다.

2. 준비

  1. Windows 10
  2. VScode
    1. Spring boot extensions
  3. Java 11
  4. Mysql 8.0.26 + Mysql Workbench ( Mysql IDE )
  5. Docker 20.10.7 on Windows10

3. Spring initialize

Spring boot extensions, Spring Initializr Java Support가 설치되어 있다면 F1 입력하여 VSCode 명령창을 열고 Spring Initializ을 입력한다.

 

VSCode에서 spring initializr 실행

원하는 버전과 패키지를 설정하고 Choose dependencies 항목에서 Spring Boot DevTools ,
Spring Data JPA , Spring Web 을 선택한다.

build.gradle파일을 열어 mysql-connector-java:8.0.26dependencies에 추가한다.

📃 build.gradle

dependencies {
    implementation 'mysql:mysql-connector-java:8.0.26'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

클라이언트에 설치된 Mysql 버전과 동일한 connector를 설정한다.

Dependencies update를 위해 다음과 같이 VSCode에서 update한다.

 

gradle 업데이트

4. Code

📃 application.propertie

spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://127.0.0.1:13306/practice?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=1234
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.show-sql=true

Mysql 의 Default 포트는 3306 이다. 자신의 환경에 맞게 설정하자.

📃 Book.java

package com.jpa.example.demo.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Book {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  private String name;

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

}

📃 BookRepository.java

package com.jpa.example.demo.model;

import org.springframework.data.repository.CrudRepository;

public interface BookRepository extends CrudRepository<Book, Long>{

}

📃 BookController.java

package com.jpa.example.demo.controller;

import com.jpa.example.demo.model.Book;
import com.jpa.example.demo.model.BookRepository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.HttpServerErrorException;

@Controller
@RequestMapping("/book")
public class BookController {

  private BookRepository bookRepository;

  @Autowired
  public BookController(BookRepository bookRepository) {
    this.bookRepository = bookRepository;
  }

  @PostMapping("/create")
  public @ResponseBody Book insertBook(@RequestBody Book param) {
    if ( param.getName().isEmpty() ) {
      throw new HttpServerErrorException(HttpStatus.BAD_REQUEST);
    }

    Book newBook = new Book();
    newBook.setName(param.getName());

    return bookRepository.save(newBook);
  }

  @GetMapping("/selectAll")
  public @ResponseBody Iterable<Book> selectAllBooks() {
    return bookRepository.findAll();
  }

}
  • Book 클래스는 Entity로서 테이블 오브젝트로 매핑된다. JPA 설정에 따라 기동 시 자동으로 생성 및 갱신된다.
  • Book 클래스를 핸들링하는 BookRepository 인터페이스를 생성한다. 스프링에서 자동으로 Implement 객체를 생성하고 빈으로 등록, 관리한다.

 

5. Mysql on Docker

본 블로그에서는 Docker설치는 다루지 않는다.

Docker volume

Mysql 데이터의 영속성을 위한 volume 을 매핑한다.

docker volume create mysql
docker volume create mysql_config

Docker run

docker run --rm -d -v mysql:/var/lib/mysql -v mysql_confg:/etc/mysql -p 13306:3306 --name mysqldb -e MYSQL_ROOT_PASSWORD=1234 mysql
  • 기존 3306포트를 사용하고 있어 13306으로 포트를 설정했다. ( 포트 충돌이 없다면 3306:3306 으로 매핑한다. )
  • MYSQL_ROOT_PASSWORD 환경변수를 사용하여 비밀번호를 설정한다.

컨테이너 기동 확인

λ docker ps

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                                    NAMES  
083448b4e3a3   mysql     "docker-entrypoint.s…"   58 minutes ago   Up 58 minutes   33060/tcp, 0.0.0.0:13306->3306/tcp, :::13306->3306/tcp   mysqldb

Mysql 컨테이너 접속

λ docker exec -it mysqldb bash
root@083448b4e3a3:/#
  • 위에서 설정한 비밀번호를 입력하고 mysql 로 접속하여 데이터베이스를 생성한다.

Database 생성

mysql> create database practice;

Mysql 워크벤치가 없다면 콘솔에서 테이블 및 데이터 생성 결과를 확인한다.

6. Spring 기동

모든 설정이 끝났다. 스프링 부트 기동 시 Book Entity가 테이블로 생성되는지 확인해보자.

<.. 중략 ..>
2021-09-19 14:20:30.573  INFO 76468 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2021-09-19 14:20:31.094  INFO 76468 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2021-09-19 14:20:31.145  INFO 76468 --- [  restartedMain] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
Hibernate: drop table if exists book
Hibernate: drop table if exists hibernate_sequence
Hibernate: create table book (id bigint not null, name varchar(255), primary key (id)) engine=InnoDB
Hibernate: create table hibernate_sequence (next_val bigint) engine=InnoDB
Hibernate: insert into hibernate_sequence values ( 1 )
  • book 테이블에 생성되었다. ( Mysql 콘솔에서 show tables 명령으로 확인한다. )
  • application.properties 파일에 spring.jpa.hibernate.ddl-auto 옵션으로 설정한 create 은 서비스 기동시 마다 @entity 와 매핑된 테이블을 Drop한다. update, none 옵션을 사용하여 환경에 맞게 설정한다.

7. Rest API 호출

Controller에 설정한 /create , /selectAll API를 호출하여 정상 작동하는지 확인한다.

λ curl -i -X POST http://localhost:8080/book/create -H "content-type: application/json" -d "{\"name\":\"jpa\" }"
HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sun, 19 Sep 2021 05:41:38 GMT

{"id":1,"name":"jpa"}

여러 개를 등록하고 /selectAll 을 호출해보자.

λ curl -i -X GET http://localhost:8080/book/selectAll
HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sun, 19 Sep 2021 05:43:19 GMT

[{"id":1,"name":"jpa"},{"id":2,"name":"Javascript Everywhere"},{"id":3,"name":"Let's run MEAN stack"}]

 

마무리하며..

VSCode에서 Spring boot의 Intializer사용하여 JPA환경을 손쉽게 구성하고, Docker 컨테이너에서 Mysql을 기동하여 datasource로 사용하는 방법을 살펴봤다.

JPA의 최대 장점은 DB 플랫폼에 종속적이지 않다는 것이다. Mysql뿐만 아니라 Oracle, Postgres등 다양한 DB서버를 Docker환경에서 쉽게 구축할 수 있다. datasource를 바꿔보면서 JPA의 장점을 확인해보는 것도 좋을 것이다.

다음에는 JPA를 조금 더 깊게 알아본다.

 

#docker #도커 #스프링부트 #스프링 #visual studio code #vscode #JPA #볼륨설정

반응형