슬기로운 개발생활

[Spring Boot] MySQL & JPA 연동 및 테스트 (Gradle 프로젝트)

by coco3o
반응형

SpringBoot에서 MySQL 그리고 Spring Data JPA를 연동하는 방법에 대해 알아보도록 하겠습니다.


1. 프로젝트에 의존성 추가하기

build.gradle에 의존성을 아래와 같이 추가해줍니다.

dependencies {
    implementation 'mysql:mysql-connector-java'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    }

2. application.properties 에 DB 정보 추가하기

# MySQL 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# DB Source URL
spring.datasource.url=jdbc:mysql://<IP>:<Port/<DB>?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul

# DB username
spring.datasource.username=<username>

# DB password
spring.datasource.password=<password>

# true 설정시 JPA 쿼리문 확인 가능
spring.jpa.show-sql=true

# DDL(create, alter, drop) 정의시 DB의 고유 기능을 사용할 수 있다.
spring.jpa.hibernate.ddl-auto=update

# JPA의 구현체인 Hibernate가 동작하면서 발생한 SQL의 가독성을 높여준다.
spring.jpa.properties.hibernate.format_sql=true

spring.jpa.hibernate.ddl-auto=[  ]

  • create  :  기존 테이블을 삭제하고 새로 생성 [ DROP + CREATE ]
  • create-drop  :  CREATE 속성에 추가로 어플리케이션을 종료할 때 생성한 DDL을 제거  [ DROP + CREATE + DROP ]
  • update  :  DB 테이블과 엔티티 매핑 정보를 비교해서 변경 사항만 수정 [ 테이블이 없을 경우 CREATE ] 
  • validate  :  DB 테이블과 엔티티 매핑정보를 비교해서 차이가 있으면 경고를 남기고 어플리케이션을 실행하지 않음
  • none  :  자동 생성 기능을 사용하지 않음

[ 정보 추가 예시 ]

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/bootex?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul
spring.datasource.username=test_user
spring.datasource.password=1234
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true

아래와 같이 정상적으로 실행되는 것을 볼 수 있습니다.

실행 화면

 


3. JPA Hibernate 엔티티(Entity) 생성하기

자세한 Entity 매핑 설명은 참고

 

@ToString
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tbl_memo")
@Entity
public class Memo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) //MySQL의 AUTO_INCREMENT를 사용
    private Long id;

    @Column(length = 200, nullable = false)
    private String memoText;

}

사용 어노테이션 정리

  • @Entity : DB의 테이블을 뜻함 [ Spring Data JPA 에서는 반드시 @Entity 어노테이션을 추가해야 함 ]
  • @Table : DB 테이블의 이름을 명시 [ 테이블 명과 클래스 명이 동일한 경우 생략 가능 ]
  • @Getter : Lombok의 Getter를 이용해 Getter 메소드를 생성하고 @Builder 를 이용해서 객체를 생성할 수 있게 처리한다.
    • @Builder를 이용하기 위해 @AllArgsConstructor@NoArgsConstructor 를 같이 처리해야 컴파일 에러가 발생하지 않음
  • @Id : Primary Key를 뜻함
  • @GeneratedValue : Primary Key의 키 생성 전략(Strategy)을 설정하고자 할 때 사용
    • GenerationType.IDENTITY : MySQL의 AUTO_INCREMENT 방식을 이용
    • GenerationType.AUTO(default) : JPA 구현체(Hibernate)가 생성 방식을 결정
    • GenerationType.SEQUENCE : DB의 SEQUENCE를 이용해서 키를 생성. @SequenceGenerator와 같이 사용
    • GenerationType.TABLE : 키 생성 전용 테이블을 생성해서 키 생성. @TableGenerator와 함께 사용
  • @Column : DB Column을 명시
    • @Column과 반대로 테이블에 컬럼으로 생성되지 않는 필드의 경우엔 @Transient 어노테이션을 적용한다.

Memo 클래스 실행

위와 같이 테이블 생성에 필요한 SQL이 기록되는 것을 확인할 수 있습니다.

DB에 생성된 테이블의 모습입니다.


4. JPA Repository 생성

Spring Data JPA는 JPA의 구현체인 Hibernate를 이용하기 위한 여러 API를 제공합니다.

그 중에서 가장 많이 사용되는 것이 바로 JPA Repository라는 인터페이스 입니다.

public interface MemoRepository extends JpaRepository<Memo, Long> {
}

작성된 MemoRepository는 JpaRepository를 상속하는 것만으로 모든 작업이 끝납니다.

  • MemoRepository를 이용해서 작성된 테이블에 SQL문 없이 CRUD 작업을 할 수 있게 됩니다.
  • JpaRepository의 제네릭 타입으로는 <Entity, PK의 타입>을 지정해주면 Spring Data JPA는 자동으로 스프링의 빈(bean)으로 등록됩니다.
    • [ 스프링이 내부적으로 인터페이스 타입에 맞는 객체를 생성해서 빈으로 등록 ]

5. 테스트를 통한 CRUD 기능 확인

5.1  Create 테스트

Insert를 할 때 Repository 객체의 save() 메소드를 사용합니다.

@SpringBootTest
public class MemoRepositoryTest {

    @Autowired
    MemoRepository memoRepository;

    @Test
    public void InsertDummies() {

        IntStream.rangeClosed(1, 10).forEach(i -> {
            Memo memo = Memo.builder()
                    .memoText("Sample..." + i)
                    .build();
            //Create!
            memoRepository.save(memo);
        });
    }

10개의 새로운 Memo 객체를 생성하고 MemoRepository를 이용해서 insert하는 것입니다.


5.2  Read 테스트

Select를 할 때 Repository 객체의 findById() 메소드를 사용합니다.

findById()를 통해 기본키를 넣어주면, 해당하는 객체를 Optional 타입으로 반환해줍니다.

@SpringBootTest
public class MemoRepositoryTest {

    @Autowired
    MemoRepository memoRepository;

    @Test
    public void SelectDummies() {

        Long id = 10L;

        Optional<Memo> result = memoRepository.findById(id);

        System.out.println("=============================");

        if(result.isPresent()) {
            Memo memo = result.get();
            System.out.println(memo);
        }
    }
}

findbyId()의 경우 Optional 타입으로 반환되기 때문에 한번 더 결과가 존재하는지를 체크하는 형태로 작성하게 됩니다.


 

5.3 Update 테스트

수정 작업과 등록작업은 동일하게 save()를 이용해서 처리합니다.

내부적으로 해당 엔티티의 @Id값이 일치하는지를 확인해서 insert 혹은 update 작업을 처리합니다.

@SpringBootTest
public class MemoRepositoryTest {

    @Autowired
    MemoRepository memoRepository;

    @Test
    public void UpdateDummies() {
        Memo memo = Memo.builder()
                .id(10L)
                .memoText("Update Text")
                .build();

        memoRepository.save(memo);
    }

JPA는 엔티티 객체들을 메모리상에 보관하려고 하기 때문에 특정한 엔티티 객체가 존재하는지 확인하는 select가 먼저 실행되고

해당 @Id를 가진 엔티티 객체가 있다면 update, 그렇지 않다면 insert를 실행하게 됩니다.


5.4 Delete 테스트

삭제 작업도 수정 작업과 동일한 개념으로 삭제하려는 엔티티 객체가 있는지 먼저 확인하고, 삭제합니다.

@SpringBootTest
public class MemoRepositoryTest {

    @Autowired
    MemoRepository memoRepository;

    @Test
    public void DeleteDummies() {
        Long id = 10L;

        memoRepository.deleteById(id);
    }

 

반응형

블로그의 정보

슬기로운 개발생활

coco3o

활동하기