@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
@Transactional
public Long join(Member member){
validateDuplicateMember(member);
Long memberId = memberRepository.save(member);
return memberId;
}
private void validateDuplicateMember(Member member) {
List<Member> findMembers = memberRepository.findByName(member.getName());
if(!findMembers.isEmpty()){
throw new IllegalStateException("이미 존재하는 회원입니다.");
}
}
public List<Member> findMembers(){
return memberRepository.findAll();
}
public Member findOne(Long memberId){
return memberRepository.findOne(memberId);
}
}
엔티티를 통한 데이터 변경은 트랜잭션 안에서 이루어 져야 한다.
그래서 @Transactional 저렇게 하면 모든 메소드에 붙는다.
그런데 readOnly = true
저거 하면 약간의 최적화가 된다. db갈때도 이건 readOnly 용이야~ 하면서 가기 때문
근데 저렇게 join처럼 readOnly가 아닌 것 들은 따로 트랜잭셔널을 지정해준다.
기본이 readOnly = false기 때문에 readOnly가 아니다.
간단한 검증. 저거는 그냥 런타임에러를 던져준다. 나중에 따로 커스텀에러 만들어서 통합 에러 처리 할 것 같다.
근데 저것도 문제가 있다. 동시성 문제. 멀티쓰레드 기 때문에 동시에 memberA로 가입하면 둘다 동시에 가입될 수 있다.
그래서, 최후의 방어벽을 위해 SQL 테이블 자체에서 name을 유니크 제약 조건으로 잡는 게 좋다.
'스프링데이터 + JPA > 웹 애플리케이션 개발' 카테고리의 다른 글
15. 상품 개발 (0) | 2023.11.07 |
---|---|
14. 회원 테스트 (0) | 2023.11.06 |
12. 회원 리포지토리 (0) | 2023.11.06 |
11. 애플리케이션 아키텍처 (0) | 2023.11.05 |
10. 구현 요구사항 (0) | 2023.11.05 |