@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<>();
}
@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();
}
}
@Service
@Transactional
@RequiredArgsConstructor //final이 있는 속성들만 생성자에 자동적으로 넣어주는 Lombok annotation
public class MemberService {
/*@Autowired
private MemberRepository memberRepository;*/
//좀 더 나은 Injection 방법 Constructor Injection
private final MemberRepository memberRepository; //final을 넣으면 컴파일 시점에 주입이 제대로 되는지 확인이 가능하다.
/**
* 회원 가입
* @param member
* @return
*/
@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("이미 존재하는 회원입니다.");
}
//Exception
}
//회원 전체 조회
@Transactional(readOnly = true) //조회만 하는 service에서 readOnly설정을 해주면 좀 더 최적화와 성능개선을 기대할 수 있다.
public List<Member> findMembers(){
return memberRepository.findAll();
}
@Transactional(readOnly = true)
public Member findOne(Long memberId){
return memberRepository.findOne(memberId);
}
}
테스트 요구사항
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class MemberServiceTest {
@Autowired
MemberService memberService;
@Autowired
MemberRepository memberRepository;
@Test
@Rollback(false)
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("kim1");
Member member2 = new Member();
member2.setName("kim1");
//when
memberService.join(member1);
memberService.join(member2); //예외가 발생해야 한다.
//then
}
}
💡test 코드 구동시에는 application.yml(or properties)를 별도로 구현해 설정 가능하다.
#spring boot에서는 별도의 설정이없으면 자동으로 메모리모드로 구동한다.
spring:
# datasource:
# url: jdbc:h2:mem:test
# username: sa
# password:
# driver-class-name: org.h2.Driver
#
# jpa:
# hibernate:
# ddl-auto: create-drop
# properties:
# hibernate:
# # show_sql:true
# format_sql: true
logging:
level:
org.hibernate.SQL: debug
org.hibernamte.type: trace
해당 yml에서는 datasources 설정에 대해서 따로 설정해줘도 되지만 작성을 안하면 메모리모드로 구동되기에 좀 더 간편하게 테스트 가능하다.