본문 바로가기
Back-End/Spring Data

4.회원도메인 개발

by 두두리안 2020. 12. 30.
728x90

4.회원도메인개발

  • 목차
    • 1.회원엔티티 다시보기
    • 2.회원 리포지토리 개발(Repository)
    • 3.회원 서비스 개발(Service)
    • 4.회원기능 테스트(Test)

1.회원엔티티 다시보기

Member

@Entity
@Getter @Setter
public class Member {

    @Id @GeneratedValue
    @Column(name="member_id")
    private Long id;

    private String name;

    @Embedded
    private Address address;

    @OneToMany(mappedBy = "member")
    private List<Order> orders=new ArrayList<>();

}
  • @Id @GeneratedValue 을 이용해서 기본키와 값이 자동으로 상승
  • @Column(name="member_id") 컬럼명을 member_id로 만들어줌
  • @Embedded 값타입을 사용하는곳

2.회원 리포지토리 개발(Repository)

MemberRepository

@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) //엔티티 맴버 객체를 조회 m으로 alias
                .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();
    }
}
  • @PersistenceContext , private EntityManager em; 앤티티 매니저를 가져와야한다
  • em.createQuery("select m from Member m",Member.class) //엔티티 맴버 객체를 조회 m으로 alias
  • .setParameter("name",name) 을 이용해서 (String name) 값을 -> :name 넣어준다
  • .getResultList(); 값을 리스트로 가져온다

3.회원 서비스 개발(Service)

  • 회원 등록
  • 회원 목록 조회
    @Service
    @Transactional(readOnly = true)
    @RequiredArgsConstructor
    public class MemberService {
    
      private final MemberRepository memberRepository;
    
      //회원가입
      @Transactional
      public Long join(Member member){
          validateDuplicateMember(member); //중복회원검증
          memberRepository.save(member); //영속성 컨텐츠에 member가 올라오면서 id가 key값이 된다 동시에 value도 저장된다
          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);
      }
    
  • Member

}

* @Transactional : jpa데이터의 변경이나 로직등은 트랜잭션에서 실행되어야 한다 (spring쪽 어노테이션 쓰기)
* @Transactional(readOnly = true) : 트랜잭션을 읽기모드하면서 영속성컨텍스트에 플래쉬나 더티체킹을 안한다 , DB같은경우는 단순한 읽기모드로 리소스를 줄이면서 성능향상
* @Autowired 을 이용해서 MemberRepository 주입한다
* @AllArgsConstructor : 생성자만 만들어준다
* @RequiredArgsConstructor : final만 있는 필드를 생성자로 만들어준다

#### MemberRepository 
```java
@RequiredArgsConstructor
public class MemberRepository {

    private final EntityManager em;
}
  • @RequiredArgsConstructor 을 이용해서 생성자 주입이 가능한다
  • 스프링데이터JPA여서 @Autowired 을 이용해서 가능하다 / 원래 @PersistenceContext

4.회원기능 테스트(Test)

  • 회원가입 성공
  • 회원가입 중복이름 예외 발생
    @SpringBootTest
    @Transactional
    class MemberServiceTest {
    
      @Autowired MemberService memberService;
      @Autowired MemberRepository memberRepository;
      @Autowired EntityManager em;
    
          @Test
          @Rollback(value = false)
          void 회원가입() {
    
              //given
              Member member = new Member();
              member.setName("Kim");
    
              //when
              Long savedId = memberService.join(member);//회원가입
    
              //then
              em.flush();
              assertEquals(member,memberRepository.findOne(savedId));
          }
    }
  • MemberServiceTest (회원가입)
  • join -> save -> persist : persist 해서 DB에 Insert문은 안나간다
  • Insert문은 Transactional 커밋 될때 플러쉬가 되면서 DB에 Insert문이 나간다
  • Transactional 커밋 될때 JPA 영속성 컨텍스트에 있는 맴버객체가 Insert문이 만들어지면서 나간다
  • 스프링의 @Transactional 커밋을 안하고 롤백한다(테스트)
  • em.flush -> 영속성컨텍스트의 변경된것을 DB에 반영한다
  • @Rollback(value = false) : 트랜잭션 롤백을 false로 바꾸면서 DB에 실제 값이 들어가는지 확인할수있다.

MemberRepository

@RequiredArgsConstructor
public class MemberRepository {

    private final EntityManager em;
}
  • @RequiredArgsConstructor 을 이용해서 생성자 주입이 가능한다
  • 스프링데이터JPA여서 @Autowired 을 이용해서 가능하다 / 원래 @PersistenceContext

MemberRepository

@SpringBootTest
@Transactional
class MemberServiceTest {

    @Autowired MemberService memberService;
    @Autowired MemberRepository memberRepository;
    @Autowired EntityManager em;

        @Test
        public void 중복회원예외() {
        //given
        Member member1 = new Member();
        member1.setName("Kim");

        Member member2 = new Member();
        member2.setName("Kim");

        //when
        memberService.join(member1);//회원가입

         //then
         assertThrows(IllegalStateException.class,()->memberService.join(member2));

        }
}
  • IllegalStateException : 부적절한 방식의 메소드가 호출될때
  • 앞에서 member1이 회원가입했는데 이름이 같은 member2가 회원가입했을때 오류가 발생된다

image

MemberRepository

spring:
  datasource:
    url: jdbc:h2:mem:test
    username: sa
    password:
    driver-class-name: org.h2.Driver

  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        format_sql: true
        default_batch_fetch_size: 100

logging:
  level:
    org.hibernate.SQL: debug
#    org.hibernate.type: trace
  • url: jdbc:h2:mem:test 을이용해서 메모리DB가 생겨서 테스트를 할수있다
  • Springboot에서 자동으로 이 설정을 해준다
  • springboot 는 create-drop으로 나간다
  • create는 내가가진 엔티티를 생성 create-drop 생성하고 종료시점에 drop해준다

출처

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-%ED%99%9C%EC%9A%A9-1/dashboard (JPA 웹 애플리케이션 1)

728x90

'Back-End > Spring Data' 카테고리의 다른 글

6.주문도메인개발  (0) 2020.12.30
5.상품도메인 개발  (0) 2020.12.30
3.엔티티클래스 개발2  (0) 2020.12.30
2.엔티티 클래스 개발1  (0) 2020.12.30
1.도메인 분석설계  (0) 2020.12.30