inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

스프링 DB 2편 - 데이터 접근 활용 기술

테스트 - 임베디드 모드 DB

임베디드 모드 테스트 시 sql 스크립트

해결된 질문

848

devholic

작성한 질문수 16

0

[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예/아니오) 예
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예

[질문 내용]
여기에 질문 내용을 남겨주세요.

영한 님의 강의를 수강한 뒤 간단한 게시판 프로젝트를 작업해보고 있습니다.

말씀해주신 임베디드 모드를 테스트에 적용하기 위해 다음과 같이 설정해봤습니다.

test의 resources/application.properties에는 단순히 로그와 관련된 것만 입력해두었습니다.

logging.level.org.springframework.jdbc=debug

# Can check SQL which Hibernate run and create
logging.level.org.hibernate.SQL=DEBUG

# Can check parameters which binding in SQL
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

멤버 엔티티입니다.

package com.devholic22.board.entity;

import jakarta.persistence.*;
import lombok.Data;

@Data
@Entity
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "user_name", length = 10)
    private String name;

    @Column(length = 10)
    private String password;

    public Member() {
    }

    public Member(String name, String password) {
        this.name = name;
        this.password = password;
    }
}

멤버 리포지토리입니다.

package com.devholic22.board.repository;

import com.devholic22.board.entity.Member;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberRepository extends JpaRepository<Member, Long> {
}

테스트 코드입니다.

package com.devholic22.board.repository;

import com.devholic22.board.entity.Member;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@Slf4j
@SpringBootTest
public class MemberRepositoryTest {

    @Autowired
    MemberRepository repository;

    @Test
    void save() {
        Member member = new Member("testerA", "1234");
        Member savedMember = repository.save(member);
        log.info(savedMember.toString());
    }
}

그런데 강의에서 이야기하셨던 SQL 스크립트를 만들어두지 않았는데도, 테스트가 제대로 실행되었습니다.

원래 예상했던 결과는 Table "MEMBER" not found와 같은 부분인데, 왜 이런 에러가 발생하지 않았는지 궁금합니다.

테스트 코드 결과입니다.

2022-12-11T13:15:08.008+09:00  INFO 65418 --- [           main] c.d.b.repository.MemberRepositoryTest    : Started MemberRepositoryTest in 7.134 seconds (process running for 9.374)
2022-12-11T13:15:08.427+09:00 DEBUG 65418 --- [           main] org.hibernate.SQL                        : insert into member (id, user_name, password) values (default, ?, ?)
2022-12-11T13:15:08.501+09:00  INFO 65418 --- [           main] c.d.b.repository.MemberRepositoryTest    : Member(id=1, name=testerA, password=1234)
2022-12-11T13:15:08.547+09:00  INFO 65418 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2022-12-11T13:15:08.549+09:00  INFO 65418 --- [ionShutdownHook] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed evictData of schema as part of SessionFactory shut-down'
2022-12-11T13:15:08.550+09:00 DEBUG 65418 --- [ionShutdownHook] org.hibernate.SQL                        : drop table if exists member cascade 
2022-12-11T13:15:08.555+09:00  INFO 65418 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2022-12-11T13:15:08.560+09:00  INFO 65418 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

 

임베디드모드 테스트 spring

답변 1

1

OMG

안녕하세요. Hyunjoon Choi님, 공식 서포터즈 OMG입니다.
.

h2 인메모리를 사용했을 때, ddl-auto의 기본값이 create-drop이여서 말씀하신 상황이 발생한 것 같습니다.

imagehttps://pravusid.kr/java/2018/10/10/spring-database-initialization.html

 

로그에서도 확인할 수 있는데요, 테스트 종료 시 table을 드랍하고 있네요.

drop table if exists member cascade 

해당 로그 이전 스프링 컨테이너가 실행되는 띄울 때 create 문이 확인될까요?
.
감사합니다.

0

devholic

확인하였습니다.

그렇다면

@Bean
@Profile("test")
public DataSource dataSource() {
    ...
}

와 같은 메모리 DB용 데이터소스를 직접 만들었을 경우에만 schema.sql 같은 SQL문을 별도로 만들어야 하고, 완전히 임베디드 모드를 스프링이 실행시키도록 할 때는 (질문과 같이 데이터베이스에 대한 정보들이 모두 없도록 할 때) ddl-auto의 값을 별도로 변경하지 않는 이상은 schema.sql을 작성하지 않아도 되는 것인가요? 이 경우는 @Entity@Column을 토대로 데이터베이스 테이블을 자동으로 만들어주는 것으로 이해하면 되는 것인지 궁금합니다.

 

추가) 영한 님의 자료를 더 찾아보니 예외와 트랜잭션 커밋, 롤백 - 활용 부분에서도 관련 내용이 언급되어 있네요.

image

확실히 spring.jpa.hibernate.ddl-auto=none으로 하니 강의처럼 테이블이 없는 오류가 나왔습니다.

그런데 제가 궁금한 것은 이 경우도 그렇고 지금 이 강의에서의 경우도 똑같이 메모리 DB를 사용하는 방식인데, 왜 이 강의에서는 sql 스크립트를 별도로 만들어야 한다고 하고 지금 경우에서는 sql 스크립트가 필요하지 않은지 차이를 잘 모르겠습니다.

 

SQL 스크립트의 예 (sql/schema.sql)

drop table if exists member;
create table member (
    id bigint generated by default as identity,
    member_name varchar(10),
    password varchar(10),
    primary key (id)
); 

 

영한 님의 설명

image

++ 강의를 계속 반복적으로 복습해 본 결과, JdbcTemplate을 사용했을 때는 src/test/resources/schema.sql 파일을 필요로 함을 알았습니다. 이에 반해, 위의 경우처럼 JPA를 사용했을 때는 sql 파일이 없어도 됨을 알았습니다. 또한, 이 이유는 Hibernate에도 기본 실행 스크립트가 있기 때문인 것도 알았습니다.

그렇다면 차이점의 원인은 @Entity에 있는 것인가요? 개인적으로 드는 생각은 @Entity를 통해 임베디드 데이터베이스에 테이블을 등록하게끔 Hibernate의 기본 스크립트에 작성되기 때문에 문제가 없는 것인가.. 생각이 드는데 이게 맞는 원리인지 검증되지 않아 질문드립니다. 

0

OMG

답변 드리기에 앞서 영한님의 JPA강의나 별도의 JPA 학습없이 여기까지(댓글) 추론하신 것이면 대단하네요 ^^

그렇다면 차이점의 원인은 @Entity에 있는 것인가요? 개인적으로 드는 생각은 @Entity를 통해 임베디드 데이터베이스에 테이블을 등록하게끔 Hibernate의 기본 스크립트에 작성되기 때문에 문제가 없는 것인가.

 

 

네 맞습니다.

JPA 설정

강의를 보셨다면 아시겠지만, build.gradle에 spring-data-jpa의존성을 추가한 것을 보셨을텐데요, 해당 의존성이 우리의 프로젝트에서 jpa를 사용하겠다는 준비와 같다면

@Entity는 JPA가 관리할 객체로 등록합니다.

그리고 애플리케이션이 실행될 때 DB의 테이블과 매핑이 되며, 이게 ORM(객체와 관계형 데이터베이스의 매핑)기술입니다. 댓글에 ++로 추가로 남긴 내용이 결국 JPA의 동작을 설명하신 것이며,

@Entity는 JPA에서만 사용하는 점을 참고해주세요(JdbcTemplate, jdbc, mybatis X)

 

 

0

devholic

답변 감사합니다!!

RepositoryTest의 패키지 위치가 domain인 이유

0

36

2

REQUIRES_NEW 해결 방법에 대해서 질문있습니다!!

0

31

1

update()에 사용하는 setter 질문드립니다.

0

49

1

SQL 중심적 개발의 문제점에 대한 질문

0

72

1

혹시 Containing 을 안쓰신 이유가 있을까요?

0

86

2

[공유] 스프링부트 4.x 버전 mybatis 연동

0

180

1

@repository 어노테이션

0

90

3

ItemService

0

59

1

논리 커밋, 물리 커밋 질문드립니다.

0

54

1

내부 트랜잭션 커밋은 필수인가요?

0

57

1

프록시 커넥션 객체를 반환할 때 생성하는건가요?

0

55

1

Transaction readOnly 성능 개선 (김영한님의 대한 감사인사)

2

180

2

JPQL 대신 네이티브 쿼리를 사용해야 하는 경우

0

80

1

@EventListener(ApplicationReadyEvent.class) 관련

0

88

1

트랜잭션 동기화 매니저와 데이터 소스

0

77

1

DB 관련 강의 개설 계획은 없으신건가요?

0

133

2

물리 트랜잭션 과 논리트랜잭션 용어를 맞게 이해한걸까요

0

94

1

스프링 3 버전 이상 rollbackFor 변경된듯요

1

113

1

트랜잭션 전파 질문.

0

87

1

프로젝트 오픈 에러

0

126

1

외부 트랜잭션에서 isNewTransaction이 false로 나오는거에 대해 질문드립니다

0

84

2

같은 스레드를 사용하면 트랜잭션 동기화 매니저는 같은 커넥션을 반환

0

73

1

h2 인메모리 테스트중 예약어 충돌날 경우 대처방법

0

105

1

커스텀aop와 트랜잭션을 같이 사용할때 우선순위에 관한 질문

0

98

2