인프런 - 스프링 부트와 JPA 활용1 by 김영한 을 기반으로 작성된 글입니다.
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
h2데이터베이스 서버모드로 실행해두기
JDBC URL : jdbc:h2:tcp://localhost/~/jpashop
resources>application.yml 파일 생성
resources>application.properties 삭제
yml 파일은 띄어쓰기(스페이스) 2칸으로 계층 만든다.
💻 코드
spring:
datasource:
url: jdbc:h2:tcp://localhost/~/jpashop
username: sa
password:
driver-class-name: org.h2.Driver
jpa:
hibernate:
ddl-auto: create
properties:
hibernate:
# show_sql: true
format_sql: true
logging:
level:
org.hibernate.SQL: debug
system.out
에 출력logger
에 출력💻 코드
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
private Long id;
private String username;
@Repository
public class MemberRepository {
@PersistenceContext //엔티티 매니저
private EntityManager em;
public Long save(Member member){
em.persist(member);
return member.getId();
}
public Member find(Long id){
return em.find(Member.class, id);
}
}
테스트
💻 초기 코드
package jpabook.jpashop;
import org.junit.Test;
import org.assertj.core.api.Assertions;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.jupiter.api.Assertions.*;
//SpringBoot로 Test
//RunWith : JUnit한테 Spring 과 관련해서 테스트 할것 이라고 알려줌
@RunWith(SpringRunner.class)
@SpringBootTest
public class MemberRepositoryTest {
//@Autowired를 통해 MemberRepository 인젝션 받음
@Autowired MemberRepository memberRepository;
@Test
public void testMember() throws Exception{
//given
Member member = new Member();
member.setUsername("memberA");
//when
//Ctrl + Alt + V : 변수 자동 생성 단축키
Long saveId = memberRepository.save(member);
//save 한 것 이 잘 저장되었는지 확인
Member findMember = memberRepository.find(saveId);
//then
//검증
Assertions.assertThat(findMember.getId()).isEqualTo(member.getId());
Assertions.assertThat(findMember.getUsername()).isEqualTo(member.getUsername());
}
}
실행 1 👉 ❗ 에러
org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread
❗ 해결
엔티티 매니저를 통한 모든 데이터 변경은 항상 transaction 안에서 이루어져야 한다.
테스트1 코드에 @Transactional
어노테이션 추가
실행 2 👉 성공
localhost:8082
그러나 왜 데이터가 없지?
👉 @Transactional
어노테이션이 테스트케이스에 있으면
테스트 종료 후 rollback하기 때문에 데이터를 확인할 수 없다.
이럴때는@Rollback(false)
어노테이션 추가 후 재실행!
Assertions.assertThat(findMember).isEqualTo(member);
JPA는 같은 영속성 콘텐츠 안에서 식별자가 같으면 같은 entity로 인식한다.
💻 최종 코드
package jpabook.jpashop;
//(생략)
@RunWith(SpringRunner.class)
@SpringBootTest
public class MemberRepositoryTest {
@Autowired MemberRepository memberRepository;
@Test
@Transactional
@Rollback(false)
public void testMember() throws Exception{
//given
Member member = new Member();
member.setUsername("memberA");
//when
Long saveId = memberRepository.save(member);
Member findMember = memberRepository.find(saveId);
//then
Assertions.assertThat(findMember.getId()).isEqualTo(member.getId());
Assertions.assertThat(findMember.getUsername()).isEqualTo(member.getUsername());
Assertions.assertThat(findMember).isEqualTo(member);
}
}
application.yml에 org.hibernate.type: trace
추가하기
logging:
level:
org.hibernate.type: trace
파라미터 값 확인 가능!
그러나 쿼리문에는 따로 나오지 않아서 확인하고 싶다면 외부라이브러리 활용하기
https://github.com/gavlyukovskiy/spring-boot-data-source-decorator
build.gradles
의 dependencies 에
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.6'
코드 추가