DirtyChecking 질문입니다!
252
작성한 질문수 21
회원을 수정하고, 회원의 닉네임이 중복되는 경우를 검증하고 싶었습니다. 더티체킹은 트랜잭션이 종료됐을 때 영속성 컨텍스트에서 변경된 것이 있는지 확인하고 변경된 것을 확인되면 업데이트 되는 것으로 알고 있는데요.
@Transactional
public void update(Long id, String name) {
Member member = findOne(id);
member.setName(name);
validateDuplicateMember(member);
}
private void validateDuplicateMember(Member member) {
// NullPointerException 발생 X
List<Member> findMembers = memberRepository.findByName(member.getName());
if (!findMembers.isEmpty()) {
throw new IllegalStateException("이미 존재하는 회원입니다.");
}
}제가 의도한 목적은 다음과 같습니다.
회원을 조회 -> 영속성 컨텍스트 영속상태
회원 객체에 대한 이름을 변경 -> 트랜잭션 종료 시 더티체킹 예상
현재 객체 전달
전달 된 회원의 이름을 가진 회원을 조회
중복 시 Rollback, 아니라면 commit 후 더티체킹 이후 회원 엔티티 수정
하지만 중복이 아님에도 중복 예외가 발생하길래 log를 확인해본 결과
List<Member> findMembers = memberRepository.findByName(member.getName());
를 수행하기 전에 flush()가 되는 부분을 확인 할 수 있었습니다.
의심되는 부분은 4번에서 회원을 조회하는 과정에서 쿼리를 수행해야해서, 그 과정에서 쓰기 지연 저장소에 있던 쿼리들이 flush() 된 것이 아닌가 하는 의심이 듭니다.
그럼 제가 원하는 목적을 수행하기 위해서는 메서드를 아래와 같이 변경해야만 하는지..
@Transactional
public void update(Long id, String name) {
validateDuplicateMember(name);
Member member = findOne(id);
member.setName(name);
}
private void validateDuplicateMember(String name) {
// NullPointerException 발생 X
List<Member> findMembers = memberRepository.findByName(name);
if (!findMembers.isEmpty()) {
throw new IllegalStateException("이미 존재하는 회원입니다.");
}
}다른 질문에서 중복 검증 시 영한님의 다음과 같은 답변을 확인 할 수 있었는데요.
@Transactional
public void update(Long id, String name) {
Member member = findOne(id);
validateDuplicateMember(member);
member.setName(name);
}
private void validateDuplicateMember(Member member) {
// NullPointerException 발생 X
List<Member> findMembers = memberRepository.findByName(member.getName());
if (!findMembers.isEmpty()) {
throw new IllegalStateException("이미 존재하는 회원입니다.");
}
}이 부분은 변경되기 전이고 이미 등록된 상태의 Member를 가져오는 것이기 때문에 회원 이름 수정 시 중복 가능성에 대한 예외를 검증하는 것이 아니지 않나 하는 생각이 들어서 질문드립니다..!
답변 1
1
안녕하세요, 종운 님! 공식 서포터즈 codesweaver 입니다.
JPA는 데이터베이스와 동기화 하는 포인트가 여럿 있는데요, 하나는 아시다시피 트랜잭션이 커밋되었을 때고 하나는 JPQL이 실행되기 전입니다. findByName()은 엔터티의 키를 이용한 검색이 아니기에 JPQL을 사용하는데 이 때 강제로 flush()가 발생합니다.
아래 첨부해주신 코드가 강의 코드 그대로라면.. 말씀하신것처럼 변경하려는 값에 대한 유효성 검증이 아닙니다...!! :)
감사합니다.
벌크연산에서 member.getAge 호출 시 영속성 컨텍스트에서 데이터를 가져오는건가요?
0
28
2
inheritance startegy 선택시 고려사항
0
22
1
Entity 동등성 비교
0
21
1
실무 조언 관련 질문입니다.
0
47
1
H2데이터베이스 파일 생성
0
56
2
서브쿼리 강의에서 ALL 예시 관련 질문드립니다.
0
53
2
수정또는 삭제시 영속성 엔티티에 값이 무조건 있어야 하나요?
0
52
1
JPQL 메소드와 락
0
55
1
Delivery @OneToOne
0
60
1
17강 4~5분대 테이블 값 조회가 안됩니다.
0
94
2
UnsupportedOperationException 발생
0
86
3
H2 Database 연결이 안됩니다.
0
95
2
연관관계 매핑 질문드립니다.
0
85
2
h2데이터베이스 실행오류
0
108
2
persistence.xml
0
108
2
양방향 연관관계에서 연관관계의 주인(mappedBy)을 왜 꼭 정해야 하나요?
0
80
1
영속성 컨텍스트
0
66
1
JPA 프록시
0
96
1
Native Query와 MyBatis
0
70
1
영속성 컨텍스트는 어떤 메모리에 저장되는건가요?
0
87
1
임베디드 타입 예시 코드 관련 질문
0
115
3
명시적 조인에서 별칭을 주면 왜 객체에 접근할 수 있나요
0
95
3
인텔리제이 패키지 커서 단축키 질문
0
108
2
혹시 현재는 ID 데이터 타입이 String이면 안되나요?
0
145
1





