JAVA Spring boot) 소비기록앱 소비일기 서버(Backend) 개발일지 3 - 회원 엔티티 개발(with JPA)
- 작성일 : 2022.08.25
-
작성자 : 황시아
- 팀원 : 박승지, 오성은, 황시아
- GitHub Repository : https://github.com/miro7923/soil
개발환경
- MacBook Air (M1, 2020)
- OpenJDK 11
- IntelliJ IDEA Community Edition
- Spring Boot 2.7.3(예정)
- MySQL Workbench 8.0.28
기간
- 2022.8.15 ~
주제
- 오늘의 소비에 대한 기억과 감정을 기록으로 남기고 나중에 되돌아보는 시간이 있었으면 좋겠다는 생각에 진행하게 된 프로젝트이다.
- 새로 산 물건의 사진을 찍고 그에 대한 감상을 함께 글로 남길 수 있는 기능을 메인으로 제작할 것이다.
진행상황
- 모~든 비즈니스의 시작, 회원 엔티티를 만들었다.
MemberRepository
-
모든 진행은 실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발 강의를 기반으로 했다.
-
먼저 DB에 접근해 트랜잭션을 수행할
Repository
를 만들었다.
@Repository
@RequiredArgsConstructor
public class MemberRepository {
private final EntityManager em; // 의존성 자동 주입
public Long save(Member member) {
em.persist(member);
return member.getId();
}
public List<Member> findAll() {
return em.createQuery("select m from Member m", Member.class)
.getResultList();
}
public Member findOne(Long id) {
return em.find(Member.class, id);
}
public List<Member> findByName(String name) {
return em.createQuery("select m from Member m where m.name = :name", Member.class)
.setParameter("name", name)
.getResultList();
}
}
- 회원 가입 기능과 조회 기능만 만들었다.
MemberService
Repository
와Controller
계층 사이에서 동작을 수행할Service
계층을 만들었다.
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MemberService {
private final MemberRepository memberRepository;
/**
* 회원 등록
* 중복 회원 검사 후 통과하면 다음 트랜잭션 진행
* @param member
* @return member_id
*/
@Transactional
public Long join(Member member) {
validateDuplicatedMember(member);
memberRepository.save(member);
return member.getId();
}
/**
* 중복 회원 검사
* @param member
*/
private void validateDuplicatedMember(Member member) {
List<Member> findMembers = memberRepository.findByName(member.getName());
if (!findMembers.isEmpty()) {
// username이 같은 회원이 존재하면 예외 발생
throw new IllegalStateException("이미 존재하는 회원입니다.");
}
}
/**
* id로 회원 한 명 조회
* @param id
* @return member_id
*/
public Member findMember(Long id) {
return memberRepository.findOne(id);
}
/**
* name으로 회원 한 명 조회
* @param name
* @return List<Member>
*/
public List<Member> findByName(String name) {
return memberRepository.findByName(name);
}
/**
* 회원 전체 조회
* @return List<Member>
*/
public List<Member> findMembers() {
return memberRepository.findAll();
}
}
- 다른 사람이 봤을 때 알아보기 쉽게 각 메서드에 대한 설명도 추가해 보았다. 뭔가 잘 정리된 느낌이라 좀 뿌듯하다.
회원 엔티티 테스트
- 다 만들었으니까 동작을 잘 하는지 테스트를 해 보았다.
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
@Transactional
class MemberServiceTest {
@Autowired
MemberService memberService;
@Autowired
MemberRepository memberRepository;
@Test
public void 회원가입() throws Exception {
// given
Member member = new Member("memberC");
// when
Long savedId = memberService.join(member);
// then
assertEquals(member, memberRepository.findOne(savedId)); // 결과 OK!
}
@Test
public void 중복회원검증() throws Exception {
// given
Member member = new Member("memberB");
Member member1 = new Member("memberB");
// when
memberService.join(member);
try {
memberService.join(member1); // 예외 발생해야 함
} catch (IllegalStateException e) {
return; // 결과 OK!
}
// then
fail("예외 발생해야 함");
}
}
JUit5
를 사용했다.- 그동안 예외를 직접 정의하고 던지는 코드를 작성해 본 경험이 많이 없어서 새롭고 재밌었다. 처음에는 잘 몰라서 중복 회원이 있을 경우 예외를 던지는 메서드
(validateDuplicatedMember(member))
를MemberRepository
클래스에 작성했다가 계속 테스트 통과가 안 되어서 헤멨었다. 왜냐면 다른 종류의 예외가 먼저 터지는 바람에 사용자 정의한 예외까지 오지 않았기 때문인데… 그래서 테스트 코드의catch
에 걸리지 않아서 계속 테스트가 실패했던 것 같다. 검증 메서드를MemberService
로 옮겨준 다음 테스트를 통과할 수 있었다.