728x90
@Service
@Transactional(readOnly = true)
//기본적으로 JPA는 트렌잭션 안에서 동작해야 한다.//javax,spring에서 제공하는것 두가지가 있지만 spring에서 사용하기 때문에 spring에서 제공하는것을 쓰는게 좋다.
//JPA가 조회하는것을 최적화 해준다, 읽기 전용임으로
@RequiredArgsConstructor//final 필드 값을 채워준다.
public class MemberService {
/* 주입 방법 1 : 필드 주입
@Autowired
private MemberRepository memberRepository;// 해당 주입을 바꿀수가 없기떄문에 최근에는 많이 사용하지 않느다.
*/
/* 주입 방법 2 : Setter 주입, 중간에 바뀔수 있는 문제가 있다.
private MemberRepository memberRepository;
@Autowired
public void setMemberRepository(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
*/
//주입 방법 3 : 생성자 주입 , 한번 생성되면 바뀔일이 없기 때문에 생성자에서 생성하여 준다
private final MemberRepository memberRepository;//변경될 일이 없기 때문에 final로 해주어 컴파일시 에러를 잡는다.
/*
public MemberService(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
*/
/**
*회원 가입
*/
@Transactional
public Long join(Member member){
//회원은 중복되면 안되기 때문에 validation
validateDuplicateMember(member);
memberRepository.save(member);
//em.persist를 하게되면 member ID에 값이 있다(영속화가 되기 떄문에)
return member.getId();
}
private void validateDuplicateMember(Member member) {
//EXCEPTION
List<Member> findMembers = memberRepository.findByName(member.getName());
//동시에 Member A라는 이름으로 등록을 하게 될경우 문제가 발생
//실무에서는 Member의 Name을 유니크 제약조건을 또 걸어 최악을 상황을 고려한다.
if(!findMembers.isEmpty()){
throw new IllegalStateException("이미 존재하는 회원입니다");
}
}
//회원 전체 조회
public List<Member> findMembers(){
return memberRepository.findAll();
}
//한건만 조회
@Transactional(readOnly = true)
public Member findOne(Long memberId){
return memberRepository.findOne(memberId);
}
}
- @Service
- Repository와 마찬가지로 내부에 @Component 어노테이션이 존재하며 스프링 빈으로 등록시켜준다.
- @Transactional
- 기본적으로 JPA는 트렌젝션 안에서 동작해야 한다.
- Javax, spring 두 가지에서 제공하는 것이 있지만 현재는 스프링 위에서 동작시키기 때문에 spring에서 제공하는 것을 사용하는 것을 추천한다.
- 읽기 전용일 때는 readOnly 속성을 true로 하여 최적화를 해준다(default는 false이다)
- Join : 회원가입 메서드
- 중복되면 안 되기 때문에 Validation check를 해준다.
- validation에서 이름이 존재할 경우 IllegalStateException을 발생시킨다
- 중복이 없다면 저장
- 참고) em.persist를 하게 될 경우 해당 엔티티는 그 순간부터 DB에 값을 넣지 않았어도 JPA Context에 영속화가 되기 때문에 Id와 같은 Field값이 채워져 있음을 증명할 수가 있다.
- 참고) SpringBootData Jpa 라이브러리 같은 경우 @Autowire로도 @PersistenceContext를 한 것과 똑같이 지원을 해주기 때문에 일관성 있게 Repository를 주입할 수가 있다.
- 중복되면 안 되기 때문에 Validation check를 해준다.
@RequiredArgsConstructor
public class MemberRepository {
private final EntityManager em;
}
스프링 주입 방법 3가지
필드 주입
@Autowired
private MemberRepository memberRepository;
- 문제 : 개발자가 원하는 데로 주입받는 것을 수정할 수가 없다.
Setter 주입
private MemberRepository memberRepository;
@Autowired
public void setMemberRepository(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
- 문제 : Setter를 사용하기 때문에 테스트 시점이나, 원하지 않는 시점에 값 변경이 가능하기 때문에 문제가 있다.
생성자 주입
@RequiredArgsConstructor//final 필드 값을 채워준다.
public class MemberService {
private final MemberRepository memberRepository;
}
- 생성되는 시점에만 주입해 주기 때문에 안전하다.
- 생성자가 하나면, @Autowired를 생략할 수 있다.
- final로 값을 주입하지 않을 경우 컴파일 에러를 잡을 수 있기 때문에 final 필드로 많이 사용한다.
728x90
'실전! 스프링 부트와 JPA 활용1(웹 애플리케이션 개발)' 카테고리의 다른 글
| Ch05. 상품 도메인 개발 - 상품 엔티티 개발(비즈니스 로직 추가) (0) | 2021.12.05 |
|---|---|
| Ch04. 회원 도메인 개발 - 회원 기능 테스트 (0) | 2021.12.05 |
| Ch04. 회원 도메인 개발 - 회원 Repository 개발 (0) | 2021.12.05 |
| Ch03. 애플리케이션 구현 준비 - 애플리케이션 아키텍처 (0) | 2021.12.04 |
| Ch03. 애플리케이션 구현 준비 - 구현 요구사항 (0) | 2021.12.04 |