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)//첫번째가 JPQL두번쨰가 반환타입
.getResultList(); //sql은 테이블을 대상으로 쿼리를 던지지만 jpql은 객체를 대상으로 쿼리를 던진다.
}
public List<Member> findByName(String name) {
return em.createQuery("select m from Member m where m.name = :name",
Member.class)
.setParameter("name", name)
.getResultList();//:name 요녀석은 매개변수를 바인딩하는 문법.setParameter("name", name)요것으로 name에 매개변수 name을 꽂는다.
}
}
package jpabook.jpashop.service;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional(readOnly = true)
public class MemberService {
@Autowired
MemberRepository memberRepository;
@Transactional //변경
public Long join(Member member) { validateDuplicateMember(member); //중복 회원 검증
memberRepository.save(member);//영속화 할떄 DB에 들어가기전에도 @id로만들어놓은 pk값은 항상 들어가잇따. 즉 스프링안에서 DB로 옮기기전에도 id 값은 들어가있다는의미
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);
}
}
그래서 이렇게 바꾸면 수정가능해짐~
MemberRepository memberRepository;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
대신 단점은 테스트 이후에바꿀일이 없음에도 바꿀수있게 설정되어있음…
궁극적으로 사용하는 방식은
MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
이렇게 생성자에 주입시켜버림
변경할 일 없으므로 memberRepository 선언할때 final로 선언하기
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
} 이녀석도 생략할 수있는것이 바로 lombok이용
- @RequiredArgsConstructor을클래스에 입력하면 final선언된 녀석의 생성자를 만들어준다.
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 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;
@Test
public void 회원가입() throws Exception {
//Given
Member member = new Member();
member.setName("kimseulgi");
//When
Long saveId = memberService.join(member); // 가입
//Then
ㄷ
assertEquals(member, memberRepository.findOne(saveId));
}
@Test(expected = IllegalStateException.class)
public void 중복_회원_예외() throws Exception {
//Given
Member member1 = new Member();
member1.setName("kimseulgi");
Member member2 = new Member();
member2.setName("kimseulgi");
//When
memberService.join(member1);
try{
memberService.join(member2); //예외가 발생해야 한다.
}catch (IllegalStateException e){
return;
}
fail("예외가 발생해야 한다.");
}
}
실제개발과 설정을 다르게 가져갈 수 잇고
새로운 DB로 저장하여 사용할 수 있다.
applicational.yml안에 디비 주소를 저걸로 바꾸면 H2 Db가 메모리 모드로 실행되어 테스트가능 >>>이러면 디비 안켜도 된다.
spring:
datasource:
url: jdbc:h2:mem:test
그런데 스프링은
spring:
# datasource:
# url: jdbc:h2:mem:test
# username: sa
# password:
# driver-class-name: org.h2.Driver
# jpa:
# hibernate:
# ddl-auto: create
# properties:
# hibernate:
# #show_sql: true
# format_sql: true
logging:
level:
org.hibernate.SQL: debug
org.hibernate.type: trace
이렇게 설정이 아무것도 없으면 애초에 메모리 모드로 DB를 실행
어처피 테스트랑 개발과 따로 가져가므로 이렇게 설정을 분리하는게 좋다