임베디드 모드 테스트 시 sql 스크립트
[질문 템플릿]
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.
답변 1
1
안녕하세요. Hyunjoon Choi님, 공식 서포터즈 OMG입니다.
.
h2 인메모리를 사용했을 때, ddl-auto의 기본값이 create-drop이여서 말씀하신 상황이 발생한 것 같습니다.
https://pravusid.kr/java/2018/10/10/spring-database-initialization.html
로그에서도 확인할 수 있는데요, 테스트 종료 시 table을 드랍하고 있네요.
drop table if exists member cascade 해당 로그 이전 스프링 컨테이너가 실행되는 띄울 때 create 문이 확인될까요?
.
감사합니다.
0
확인하였습니다.
그렇다면
@Bean
@Profile("test")
public DataSource dataSource() {
...
}와 같은 메모리 DB용 데이터소스를 직접 만들었을 경우에만 schema.sql 같은 SQL문을 별도로 만들어야 하고, 완전히 임베디드 모드를 스프링이 실행시키도록 할 때는 (질문과 같이 데이터베이스에 대한 정보들이 모두 없도록 할 때) ddl-auto의 값을 별도로 변경하지 않는 이상은 schema.sql을 작성하지 않아도 되는 것인가요? 이 경우는 @Entity와 @Column을 토대로 데이터베이스 테이블을 자동으로 만들어주는 것으로 이해하면 되는 것인지 궁금합니다.
추가) 영한 님의 자료를 더 찾아보니 예외와 트랜잭션 커밋, 롤백 - 활용 부분에서도 관련 내용이 언급되어 있네요.

확실히 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)
);
영한 님의 설명

++ 강의를 계속 반복적으로 복습해 본 결과, JdbcTemplate을 사용했을 때는 src/test/resources/schema.sql 파일을 필요로 함을 알았습니다. 이에 반해, 위의 경우처럼 JPA를 사용했을 때는 sql 파일이 없어도 됨을 알았습니다. 또한, 이 이유는 Hibernate에도 기본 실행 스크립트가 있기 때문인 것도 알았습니다.
그렇다면 차이점의 원인은 @Entity에 있는 것인가요? 개인적으로 드는 생각은 @Entity를 통해 임베디드 데이터베이스에 테이블을 등록하게끔 Hibernate의 기본 스크립트에 작성되기 때문에 문제가 없는 것인가.. 생각이 드는데 이게 맞는 원리인지 검증되지 않아 질문드립니다.
0
답변 드리기에 앞서 영한님의 JPA강의나 별도의 JPA 학습없이 여기까지(댓글) 추론하신 것이면 대단하네요 ^^
그렇다면 차이점의 원인은
@Entity에 있는 것인가요? 개인적으로 드는 생각은@Entity를 통해 임베디드 데이터베이스에 테이블을 등록하게끔 Hibernate의 기본 스크립트에 작성되기 때문에 문제가 없는 것인가.
네 맞습니다.
강의를 보셨다면 아시겠지만, build.gradle에 spring-data-jpa의존성을 추가한 것을 보셨을텐데요, 해당 의존성이 우리의 프로젝트에서 jpa를 사용하겠다는 준비와 같다면
@Entity는 JPA가 관리할 객체로 등록합니다.
그리고 애플리케이션이 실행될 때 DB의 테이블과 매핑이 되며, 이게 ORM(객체와 관계형 데이터베이스의 매핑)기술입니다. 댓글에 ++로 추가로 남긴 내용이 결국 JPA의 동작을 설명하신 것이며,
@Entity는 JPA에서만 사용하는 점을 참고해주세요(JdbcTemplate, jdbc, mybatis X)
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





