Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- 모두를 위한 딥러닝
- 백준 4358 자바
- HTTP
- 스터디
- 데이터베이스
- 백준 4949번
- 깃허브 토큰 인증
- 리액트 네이티브 프로젝트 생성
- 문자열
- 모두를위한딥러닝
- 깃 연동
- SQL
- 모두의 네트워크
- 머신러닝
- 백준 4358번
- 정리
- 백준 5525번
- 깃허브 로그인
- React Native
- 데베
- 딥러닝
- 자바
- 백준
- 깃 터미널 연동
- 지네릭스
- 팀플회고
- 네트워크
- 리액트 네이티브 시작하기
- 모두의네트워크
- 리액트 네이티브
Archives
- Today
- Total
솜이의 데브로그
[Spring Boot] 회원 도메인 개발 본문
Reference : Inflearn- 실전 스프링부트와 JPA 활용1 (김영한님 강의)
다음 기능들을 포함한 애플리케이션을 개발해보자.
- 회원 기능
- 회원 등록
- 회원 조회
- 상품 기능
- 상품 등록
- 상품 수정
- 상품 조회
- 주문 기능
- 상품 주문
- 주문 내역 조회
- 주문 취소
회원 리포지토리
MemberRepository.java
- @Repository : 스프링빈으로 등록하고, JPA 예외를 스프링 기반 예외로 변환
- @PersistenceContext : 엔티티 매니저 주입
- @PersistenceUnit : 엔티티 매니저 팩토리 주입
package jpabook.jpashop.repository;
import jpabook.jpashop.domain.Member;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
@Repository
public class MemberRepository {
@PersistenceContext
private EntityManager em;
public void save(Member member){
em.persist(member);
}
public Member findOne(Long id){
return em.find(Member.class, id);
}
public List<Member> findAll() {
return em.createQuery("select m from Member m", Member.class).getResultList();
}
//이름으로 조회
public List<Member> findByName(String name){
return em.createQuery("select m from Member m where m.name = :name", Member.class).setParameter("name", name).getResultList();
}
}
- save() : persist로 멤버 엔티티 넣고, 트랜잭션이 커밋되는 시점에 db에 반영됨. (insert query가 날라감)
- findOne() : 단건 조회. 멤버를 조회해서 반환
- findAll() : JPQL을 사용해서 query 생성. (SQL과 비슷한데 FROM의 대상이 테이블이 아닌 엔티티가 된다.)
- findByName() : Parameter binding해서 특정 이름의 회원만 찾는다.
회원 서비스
service package / MemberService.java
- @Service : Component scan의 대상이 되어 자동으로 등록됨.
- @Transactional : 트랜잭션, 영속성 컨텍스트.
- readOnly=true : 데이터 변경이 없는 읽기 전용 메서드에 사용한다. 약간의 성능 향상 (읽기 모드만!!!)
- 데이터베이스 드라이버가 지원시 DB에서 성능 향상
- 기본적으로 두면 readOnly=false 이므로 필요한 상황에 따라 사용
- @Autowired : 생성자 Injection 많이 사용
package jpabook.jpashop.service;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@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()) {
//EXCEPTION
throw new IllegalStateException("이미 존재하는 회원입니다.");
}
}
//회원 전체 조회
public List<Member> findMembers(){
return memberRepository.findAll();
}
//회원 단건 조회
public Member findOne(Long memberId){
return memberRepository.findOne(memberId);
}
}
- 중복 검증 시 실무에서는 멀티 쓰레드 상황을 고려하여 회원 테이블의 회원명 컬럼에 유니크 제약을 추가하는 것이 안전하다.
회원 기능 테스트
- 회원 가입에 성공해야함
- 회원 가입 시 같은 이름이 있으면 예외 발생
- @RunWith(SpringRunner.class) : 스프링과 테스트 통합.
- @SpringBootTest : 스프링 부트를 띄운 상태에서 테스트 실행. (있어야 @Autowired 실행)
- @Transactional : 테스트 실행할때마다 트랜잭션 시작하고, 테스트 끝나면 트랜잭션을 강제로 롤백한다. 반복 가능한 테스트 지원.
package jpabook.jpashop.service;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.repository.MemberRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class MemberServiceTest {
@Autowired MemberService memberService;
@Autowired MemberRepository memberRepository;
@Autowired EntityManager em;
@Test
public void 회원가입() throws Exception {
//given
Member member = new Member();
member.setName("kim");
//when
Long savedId = memberService.join(member);
//then
assertEquals(member, memberRepository.findOne(savedId));
}
@Test(expected = IllegalStateException.class)
public void 중복_회원_예외() throws Exception{
//given
Member member1 = new Member();
member1.setName("kim");
Member member2 = new Member();
member2.setName("kim");
//when
memberService.join(member1);
memberService.join(member2); //예외가 발생해야 한다!!
//then
fail("예외가 발생해야 한다.");
}
}
★ 테스트 케이스 실행 시, Gvien, When, Then 사용해서 각각의 케이스 설정해서 작성하면 편하다!
test/resources/application.yml
spring:
logging:
level:
org.hibernate.SQL: debug
org.hibernate.type: trace
파일에 원하는 설정대로 하면 메모리 DB를 따로 사용하여 격리된 환경에서 테스트를 실행할 수 있다.
테스트 케이스를 위한 스프링 환겨과, 일반적으로 애플리케이션을 실행하는 환경이 다르므로 설정 파일을 다르게 사용하자.
위의 파일을 설정하면 테스트에서 스프링을 실행 시 이 위치에 있는 설정 파일을 읽는다.
(이 위치에 없으면 src/resources/application.yml 을 읽는다.)
'dev > Spring Boot' 카테고리의 다른 글
[SpringBoot] 웹 계층 개발(1) (0) | 2022.03.25 |
---|---|
[Spring Boot] 주문 도메인 개발(2) (0) | 2021.12.03 |
[Spring Boot] 주문 도메인 개발(1) (0) | 2021.11.17 |
[Spring Boot] 상품 도메인 개발 (0) | 2021.11.15 |
[Spring Boot] 엔티티 설계 시 주의점 (0) | 2021.10.09 |