01 프로젝트 환경설정 - JPA & DB

shin·2023년 7월 22일
0

5. JPA와 DB 설정 동작확인

1) application.yml

  • 정이 복잡해지면 yml 작성 방식이 편하기 때문에 application.yml 파일에 동작 설정
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

server:
  port: 8000
  • jpa hibernate가 생성하는 SQL 출력

    • System.out 콘솔에 출력하는 방법
      • jpa.hibernate.show_sql
      • 운영 환경에서는 해당 설정을 사용하면 안됨
    • log로 찍어내는 방법
      • logging.level.org.hibernate.SQL
  • 로그, 콘솔의 SQL을 좀 더 예쁘게 출력해주는 설정

    • jpa.hibernate.format-sql
  • 애플리케이션 실행 시점에 갖고 있던 테이블을 지우고 다시 새로 생성하는 설정

    • jpa.hibernate.ddl-auto: create

2) Entity

package jpabook.jpashop;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter @Setter
public class Member {

    @Id @GeneratedValue /PK 매핑
    private Long id;
    private String userName;
}

3) Repository

package jpabook.jpashop;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;

@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);
    }
}
  • @PersistenceContext
    • EntityManger를 빈으로 주입할 때 사용하는 어노테이션
    • EntityManger를 통해 PersistenceContext에 접근
    • EntityManger의 persist 메서드를 통해 엔티티를 저장함
    • 내용 추가 정리 : https://velog.io/@syb0228/JPA-Persistence
  • @Autowired : 스프링 빈 주입
  • @PersistenceContext : JPA 스펙에서 제공하는 기능으로, 영속성 컨텍스트를 주입

4) Junit

  • Junit4 사용
package jpabook.jpashop;

import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringRunner.class)
@SpringBootTest
public class MemberRepositoryTest {

    @Autowired MemberRepository memberRepository;

    @Test
    @Transactional
    @Rollback(false)
    public void testMember() {
        //given
        Member member = new Member();
        member.setUserName("memberA");

        //when
        Long savedId = memberRepository.save(member);
        Member findMember = memberRepository.find(savedId);

        //then
        Assertions.assertThat(findMember.getId()).isEqualTo(member.getId());
        Assertions.assertThat(findMember.getUserName()).isEqualTo(member.getUserName());
        Assertions.assertThat(findMember).isEqualTo(member);
    }
}

테스트 시 주의 사항

  • H2 데이터베이스를 켜놓은 상태에서 테스트를 수행해야 함

  • @Transactional 선언 필수

    • JPA는 기본적으로 transaction을 기반으로 작동
    • transaction 단위에 따라 1차캐시영역에 있는 객체들이 db에 flush되어 영속화되기 때문
    • 영속 작업을 하는 persist() 메서드에 객체가 들어갔을 때 가능한 transaction이 존재하지 않으면 아래와 같은 에러가 발생함
  No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
  • 데이터를 남겨놓기 위해선 @Rollback(false) 추가 필수

    • @Transactional이 test case에 있으면 test가 끝난 후에 자동으로 디비를 Rollback 해버림
    • @Rollback(false)를 추가해서 롤백 없이 데이터가 반영되도록 함
  • 이전에 ddl-auto: create로 설정했기 때문에 생성하고자 하는 member 테이블이 이미 존재하는지 확인 후 존재한다면 drop한 후에 새로 create 해줌

모든 테스트 통과

  • 같은 transaction 안에서 저장하고 조회를 하면 영속성 컨텍스트가 같음
  • 같은 영속성 컨텍스트 안에서는 Id 값이 같으면 같은 엔티티로 식별함
  • 1차캐시영역에 있는 똑같은 객체를 꺼내옴

5) H2 DB 테이블 생성확인


6) 쿼리 파라미터 로그 남기기

  • SQL 파라미터를 로그로 남김
    • 스프링 부트 3.x, hibernate6
    org.hibernate.orm.jdbc.bind: trace
  • 외부 라이브러리 사용

  • 이전에는 ?로 표시되었는데, 해당 설정을 통해 어떤 데이터인지 명확한 확인이 가능해짐

강의 : 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

profile
Backend development

0개의 댓글