해결된 질문
작성
·
736
·
수정됨
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.
답변 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 문이 확인될까요?
.
감사합니다.
답변 드리기에 앞서 영한님의 JPA강의나 별도의 JPA 학습없이 여기까지(댓글) 추론하신 것이면 대단하네요 ^^
그렇다면 차이점의 원인은
@Entity
에 있는 것인가요? 개인적으로 드는 생각은@Entity
를 통해 임베디드 데이터베이스에 테이블을 등록하게끔 Hibernate의 기본 스크립트에 작성되기 때문에 문제가 없는 것인가.
네 맞습니다.
강의를 보셨다면 아시겠지만, build.gradle에 spring-data-jpa의존성을 추가한 것을 보셨을텐데요, 해당 의존성이 우리의 프로젝트에서 jpa를 사용하겠다는 준비와 같다면
@Entity는 JPA가 관리할 객체로 등록합니다.
그리고 애플리케이션이 실행될 때 DB의 테이블과 매핑이 되며, 이게 ORM(객체와 관계형 데이터베이스의 매핑)기술입니다. 댓글에 ++로 추가로 남긴 내용이 결국 JPA의 동작을 설명하신 것이며,
@Entity는 JPA에서만 사용하는 점을 참고해주세요(JdbcTemplate, jdbc, mybatis X)
확인하였습니다.
그렇다면
와 같은 메모리 DB용 데이터소스를 직접 만들었을 경우에만
schema.sql
같은 SQL문을 별도로 만들어야 하고, 완전히 임베디드 모드를 스프링이 실행시키도록 할 때는 (질문과 같이 데이터베이스에 대한 정보들이 모두 없도록 할 때) ddl-auto의 값을 별도로 변경하지 않는 이상은schema.sql
을 작성하지 않아도 되는 것인가요? 이 경우는@Entity
와@Column
을 토대로 데이터베이스 테이블을 자동으로 만들어주는 것으로 이해하면 되는 것인지 궁금합니다.추가) 영한 님의 자료를 더 찾아보니
예외와 트랜잭션 커밋, 롤백 - 활용
부분에서도 관련 내용이 언급되어 있네요.확실히
spring.jpa.hibernate.ddl-auto=none
으로 하니 강의처럼 테이블이 없는 오류가 나왔습니다.그런데 제가 궁금한 것은 이 경우도 그렇고 지금 이 강의에서의 경우도 똑같이 메모리 DB를 사용하는 방식인데, 왜 이 강의에서는 sql 스크립트를 별도로 만들어야 한다고 하고 지금 경우에서는 sql 스크립트가 필요하지 않은지 차이를 잘 모르겠습니다.
SQL 스크립트의 예 (sql/schema.sql)
영한 님의 설명
++ 강의를 계속 반복적으로 복습해 본 결과, JdbcTemplate을 사용했을 때는
src/test/resources/schema.sql
파일을 필요로 함을 알았습니다. 이에 반해, 위의 경우처럼 JPA를 사용했을 때는 sql 파일이 없어도 됨을 알았습니다. 또한, 이 이유는 Hibernate에도 기본 실행 스크립트가 있기 때문인 것도 알았습니다.그렇다면 차이점의 원인은
@Entity
에 있는 것인가요? 개인적으로 드는 생각은@Entity
를 통해 임베디드 데이터베이스에 테이블을 등록하게끔 Hibernate의 기본 스크립트에 작성되기 때문에 문제가 없는 것인가.. 생각이 드는데 이게 맞는 원리인지 검증되지 않아 질문드립니다.