Spring-회원 도메인과 리포지토리 생성

snowball moon·2023년 10월 1일
0

Spring-입문

목록 보기
9/14

회원 객체

com.example.spring에 domain package를 생성한다.

Member라는 class를 만들어준다.

package hello.hellospring.domain;
public class Member {
 
 private Long id;
 private String name;
 public Long getId() {
 return id;
 }
 public void setId(Long id) {
 this.id = id;
 }
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
}

요구사항에서 id 식별자와 이름이 있었다.
id는 임의의 값으로 고객이 정하는 아이디가 아니라 시스템이 저장하는 아이디이고 name은 단순히 고객의 이름이다.

Getter Setter를 만들어준다.

회원 repository interface

package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.List;
import java.util.Optional;
public interface MemberRepository {
 Member save(Member member);
 Optional<Member> findById(Long id);
 Optional<Member> findByName(String name);
 List<Member> findAll();
}

회원을 저장하는 저장소를 만들어 주는데 repository package안에 MemberRepository interface를 생성한다.

//회원을 저장하면 저장된 회원을 반환해준다.
Member save(Member member);
//회원을 찾아준다.
Optional<Member> findById(Long id);
Optional<Member> findByName(String name);
//저장된 모든 회원 리스트를 반환해준다.
List<Member> findAll();

여기서 Optional은 Java8에 들어간 기능으로 findByName이나 findById로 가져올 때 null일 수 있는데 없으면 null로 반환된다. 이때 null을 처리하는 방법 중 null을 그대로 반환하는 방법 대신 Optional로 감싸서 반환하는 방법을 써주는 것이다.

Optional은 null을 반환하면 오류가 발생할 가능성이 매우 높은 경우에 '결과 없음'을 명확하게 드러내기 위해 메소드의 반환 타입으로 사용되도록 매우 제한적인 경우로 설계되었다.

Optional을 올바르게 사용하지 않으면 부작용을 유발하는데 NoSuchElementException이 발생할 수 있고 코드의 가독성을 떨어뜨리고 시공간적 비용이 증가한다.

Optional은 객체를 감싸는 컨테이너이므로 객체 자체를 저장하기 위한 메모리가 추가되고 객체를 얻을 때에는 Optional 객체를 통해 접근하므로 접근 비용이 증가한다.

그러므로 Optional을 사용할 때에는 Optional 변수에 Null을 할당하지 말아야 하고 값이 없을 때에는 Optional.orElseX()로 기본 값을 반환해야 하며 단순 값을 얻으려는 목적으로만 Optional을 사용하지 말고 생성자,수정자,메소드 파라미터 등으로 Optional을 넘기지 말아야 한다. 그리고 반환 타입으로만 사용해야 한다.

회원 repository 메모리 구현체

package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.*;
/**
 * 동시성 문제가 고려되어 있지 않음, 실무에서는 ConcurrentHashMap, AtomicLong 사용 고려
 */
public class MemoryMemberRepository implements MemberRepository {
 private static Map<Long, Member> store = new HashMap<>();
 private static long sequence = 0L;
 @Override
 public Member save(Member member) {
 member.setId(++sequence);
 store.put(member.getId(), member);
 return member;
 }
 @Override
 public Optional<Member> findById(Long id) {
 return Optional.ofNullable(store.get(id));
 }
 @Override
 public List<Member> findAll() {
 return new ArrayList<>(store.values());
 }
 @Override
 public Optional<Member> findByName(String name) {
 return store.values().stream()
 .filter(member -> member.getName().equals(name))
 .findAny();
 }
 public void clearStore() {
 store.clear();
 }
}

아까 생성했던 MemberRepository interface를 implement 한 후 implement method를 해준다.

private static Map<Long, Member> store = new HashMap<>();
 private static long sequence = 0L;

구현을 하기 위해서는 저장을 해야하는데 HashMap을 써준다.(실무에서는 동시성 문제가 있을 수 있기 때문에 ConcurrentHashMap을 쓴다.)
sequence는 0,1,2 이런 식으로 키 값을 생성해준다.
(실무에서는 동시성 문제를 고려해서 AtomicLong을 쓴다.)

  @Override
    public Member save(Member member) {
        member.setId(++sequence);
        store.put(member.getId(), member);
        return member;
    }

setId를 할 때 먼저 sequence의 값을 하나 올려주고 store에 넣기 전에 멤버의 id 값을 세팅 해준다.
그 다음 store에 저장을 하고 맵에 저장된다.

@Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id));
    }

store에서 꺼내는데 null이 반환될 가능성이 있을 때 Optional로 감싸준다.

@Override
    public Optional<Member> findByName(String name) {
        return store.values().stream()
                .filter(member -> member.getName().equals(name))
                .findAny();
    }

member.getName이 파라미터로 넘어온 name이랑 같은지 확인하는데 같은 경우 filtering되고 그 중에서 찾으면 반환을 한다.
findAny는 결과가 Optional로 그냥 반환된다.
루프를 다 돌았는데 없으면 Optional에 null이 포함되어서 반환된다.

@Override
    public List<Member> findAll() {
        return new ArrayList<>(store.values());

    }

new ArrayList로 store.values를 반환해주면 된다.
store에 있는 values가 멤버들이다.

References

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8
https://mangkyu.tistory.com/203

0개의 댓글