📘스프링부트

Repository개발

@Repository : 스프링 빈으로 등록, JPA 예외를 스프링 기반 예외로 예외 변환 @PersistenceContext : 엔티티 메니저( EntityManager ) 주입 @PersistenceUnit : 엔티티 메니터 팩토리( EntityManagerFactory ) 주입//거의 안씀 PersistenceContext가 있어서


@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(){ //jpql문법을 사용하여 검색
        return em.createQuery("select m from Member m ",Member.class)
                .getResultList();
    }

    public List<Member> findbyName(String name){ //jpql문법을 사용하여 검색
        return em.createQuery("select m from Member m.name = :name", Member.class)
                .setParameter("name",name)
                .getResultList();
    }
}

service 개발

생성자 주입 방식을 권장 변경 불가능한 안전한 객체 생성 가능 생성자가 하나면, @Autowired 를 생략할 수 있다. @RequiredArgsConstructor 을 사용하면 Autowired생략할수있고, final 키워드를 추가하면 컴파일 시점에 memberRepository 를 설정하지 않는 오류를 체크할 수 있다. (보통 기본 생성자를 추가할 때 발견) @Transactional : 트랜잭션, 영속성 컨텍스트,데이터베이스의 상태를 변화시키기 해서 수행하는 작업의 단위를 뜻한다. readOnly=true : 데이터의 변경이 없는 읽기 전용 메서드에 사용, 영속성 컨텍스트를 플러시 하지 않으므로 약간의 성능 향상(읽기 전용에는 다 적용) 데이터베이스 드라이버가 지원하면 DB에서 성능 향상

@Service
@Transactional(readOnly = true) //데이터 베이스 상태 변화
@RequiredArgsConstructor //Autowired를 생략하고 final 키워드 추가
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);
    }
}

test개발

@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 saveId = memberService.join(member);
        //then
         em.flush();//데이터 베이스에 반영할수있다.
        assertEquals(member,memberRepository.findOne(saveId));
    }
    @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("예외가 발생해야 한다.");
    }

}

테스트 케이스를 위한 설정 테스트는 케이스 격리된 환경에서 실행하고, 끝나면 데이터를 초기화하는 것이 좋다. 그런 면에서 메모리 DB를 사용하는 것이 가장 이상적이다. 추가로 테스트 케이스를 위한 스프링 환경과, 일반적으로 애플리케이션을 실행하는 환경은 보통 다르므로 설정 파일을 다르게 사용하자. 다음과 같이 간단하게 테스트용 설정 파일을 추가하면 된다.

test/resources/application.yml

이제 테스트에서 스프링을 실행하면 이 위치에 있는 설정 파일을 읽는다. (만약 이 위치에 없으면 src/resources/application.yml 을 읽는다.) 스프링 부트는 datasource 설정이 없으면, 기본적을 메모리 DB를 사용하고, driver-class도 현재 등록된 라이브러를 보고 찾아준다. 추가로 ddl-auto 도 create-drop 모드로 동작한다. 따라서 데이터소스나, JPA 관련된 별도의 추가 설정을 하지 않아도 된다.

태그:

카테고리:

업데이트: