프로그래밍/spring boot

[스프링부트] 실전! 스프링 부트와 JPA 활용1 #4-2 회원 서비스 개발

aSpring 2023. 11. 2. 09:11
728x90
728x90
※ 본 포스팅은 김영한 강사님의 인프런 '실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발' 강의를 들으며 작성한 수강일지 입니다.

 

| 회원 도메인 개발

1. 회원 리포지토리 개발
2. 회원 서비스 개발
3. 회원 기능 테스트

 

2. 회원 서비스 개발

package jpabook.jpashop.service;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional(readOnly = true)
public class MemberService {
 @Autowired
 MemberRepository memberRepository;
 /**
 * 회원가입
 */
 @Transactional //변경
 public Long join(Member member) {
 validateDuplicateMember(member); //중복 회원 검증
 memberRepository.save(member);
 return member.getId();
 }
 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);
 }
}

기술 설명

  • @Service
  • @Transactional : 트랜잭션, 영속성 컨텍스트
    • readOnly=true : 데이터의 변경이 없는 읽기 전용 메서드에 사용, 영속성 컨텍스트를 플러시 하지 않 으므로 약간의 성능 향상(읽기 전용에는 다 적용)
    • 데이터베이스 드라이버가 지원하면 DB에서 성능 향상
  • @Autowired
    • 생성자 Injection 많이 사용, 생성자가 하나면 생략 가능

 

기능 설명

  • join()
  • findMembers()
  • findOne()

 

참고: 실무에서는 검증 로직이 있어도 멀티 쓰레드 상황을 고려해서 회원 테이블의 회원명 컬럼에 유니크 제 약 조건을 추가하는 것이 안전하다.

 

참고: 스프링 필드 주입 대신에 생성자 주입을 사용하자

 

필드 주입

public class MemberService {
 @Autowired
 MemberRepository memberRepository;
 ...
}

생성자 주입

public class MemberService {
 private final MemberRepository memberRepository;
 public MemberService(MemberRepository memberRepository) {
 this.memberRepository = memberRepository;
 }
 ...
}
  • 생성자 주입 방식을 권장
  • 변경 불가능한 안전한 객체 생성 가능
  • 생성자가 하나면, @Autowired를 생략할 수 있다.
  • final 키워드를 추가하면 컴파일 시점에 memberRepository를 설정하지 않는 오류를 체크할 수 있다. (보통 기본 생성자를 추가할 때 발견)

lombok

@RequiredArgsConstructor
public class MemberService {
 private final MemberRepository memberRepository;
 ...
}
참고 : 스프링 데이터 JPA를 사용하면 EntityManager도 주입 가능
@Repository
@RequiredArgsConstructor
public class MemberRepository {
 private final EntityManager em;
 ...
}

 

MemberService 최종 코드

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class MemberService {
 private final MemberRepository memberRepository;
 /**
 * 회원가입
 */
 @Transactional //변경
 public Long join(Member member) {
 validateDuplicateMember(member); //중복 회원 검증
 memberRepository.save(member);
 return member.getId();
 }
 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);
 }
}
728x90
728x90