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 출력
jpa.hibernate.show_sql
logging.level.org.hibernate.SQL
로그, 콘솔의 SQL을 좀 더 예쁘게 출력해주는 설정
jpa.hibernate.format-sql
애플리케이션 실행 시점에 갖고 있던 테이블을 지우고 다시 새로 생성하는 설정
jpa.hibernate.ddl-auto: create
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;
}
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
@Autowired
: 스프링 빈 주입@PersistenceContext
: JPA 스펙에서 제공하는 기능으로, 영속성 컨텍스트를 주입
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
선언 필수
transaction
을 기반으로 작동transaction
단위에 따라 1차캐시영역에 있는 객체들이 db에 flush되어 영속화되기 때문persist()
메서드에 객체가 들어갔을 때 가능한 transaction
이 존재하지 않으면 아래와 같은 에러가 발생함 No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
데이터를 남겨놓기 위해선 @Rollback(false)
추가 필수
@Rollback(false)
를 추가해서 롤백 없이 데이터가 반영되도록 함이전에 ddl-auto: create
로 설정했기 때문에 생성하고자 하는 member
테이블이 이미 존재하는지 확인 후 존재한다면 drop
한 후에 새로 create
해줌
transaction
안에서 저장하고 조회를 하면 영속성 컨텍스트가 같음영속성 컨텍스트
안에서는 Id 값이 같으면 같은 엔티티로 식별함org.hibernate.orm.jdbc.bind: trace