인프런 커뮤니티 질문&답변

GSP님의 프로필 이미지
GSP

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

안녕하세요! 엔티티메니저와 트랜잭션의 상관관계에 대한 질문이 있어 글을 올립니다!!

작성

·

144

0

- 해당코드는 회원정보를 저장하는 테스트 코드입니다

@Test
public void testmember() throws Exception {
String named = "현우";
String street = "서울시";
String zipcode = "강남구";
Address address = new Address(zipcode, street);



//새로운 방식
memberRepository.save(Member.builder()
.name(named)
.address(address)
.coupon(천원)
.build());

List<Member> mm = memberRepository.findAll();
Member member = mm.get(0);
System.out.println(member.getCreatedDate());
assertThat(member.getName()).isEqualTo(named);



- memberRepository 코드 

@Repository
@RequiredArgsConstructor
public class MemberRepository {

@PersistenceContext
private final EntityManager em;

public void save(Member member) {

em.persist(member); //1차캐시에저장

}

레포지토리 코드에서 persist를 날릴 경우 1차캐시에만 저장되고 db에는 저장되지 않는다고 말씀 하셨는데 @Rollback(false)를 하고
테스트 코드를 돌린 결과 H2데이터베이스에 값이 들어가 있는 것을 확인 하였습니다.

여기서 두가지 의문점이 들었습니다

1. @Transaction어노테이션을 선언한 함수에서 해당 트랜잭션이 끝날때 flush를 하지 않아도 자동적으로 DB에 커밋이 되는건가?
2. @Transaction어노테이션을 선언하지 않아도 EntityManager em만을 사용한 함수 내부에서 알아서 트랜잭션 처리가 되어 함수가
끝나면 DB에 값이 저장이 되는건가?
엄청 초보적인 질문이지만 꼭 답변 달아주시면 감사하겠습니다 !

답변 2

1

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요 GSP님^^

초보적인 질문은 없습니다. 그냥 하나라도 더 배우고 싶은 개발자가 있을 뿐입니다^^!

우선 설명하신 내용을 읽어보니 테스트 클래스 상단에 @Transactional + @Rollback(false)를 사용하셨군요.

1번을 먼저 말씀드릴께요.

JPA는 기본적으로 트랜잭션을 커밋할 때 자동으로 em.flush()를 먼저 호출하고 트랜잭션을 커밋하도록 되어있습니다.

그렇지 않으면 DB에 데이터가 없는 상태로 commit이 되는 슬픈 일이 발생하겠지요.

스프링에서 @Transactional을 사용해도 마찬가지 입니다. @Transactional이 끝나는 시점에 트랜잭션을 커밋하는데, 이때 em.flush()를 먼저 호출하고 그 다음에 실제 커밋이 일어납니다.

(스프링부트를 사용하시면 JPA를 자동으로 인식해서 JpaTransactionManager 빈이 등록되고, 여기에서 @Transactional과 연계해서 JPA와 관련된 트랜잭션 처리를 해줍니다.)

2번은 트랜잭션 없이 em.persist()를 호출하면 오류가 발생합니다. JPA의 모든 데이터 변경은 트랜잭션 안에서 처리되어야 합니다^^

감사합니다.

0

GSP님의 프로필 이미지
GSP
질문자

답변감사합니다 ^ㅡ^

GSP님의 프로필 이미지
GSP

작성한 질문수

질문하기