개발은 도메인 -> 레포지토리 -> 서비스 -> 뷰 -> 컨트롤러
@Component
public @interface Repository {}
@Repository
이 어노테이션이 스프링 빈으로 관리 될 수 있는 이유는, 인터페이스에 @Component가 있기 때문
@SpringBootAplication
하위 모든 파일과 패키지를 컴포넌트 스캔
@PersistenceContext
스프링부트가 의존성을 주입, JPA만 사용한다면 엔티티 매니저 팩토리 만들고 해야하는데
빈으로 관리되기 때문에 필요 없음
@Repository // 어노테이션 등록 시 자동으로 스프링 빈으로 관리
public class MemberRepository {
@PersistencContext
private final EntityManager em;
public memberRepository(EntityManager em){
this.em = em;
}
@Repository // 어노테이션 등록 시 자동으로 스프링 빈으로 관리
@RequiredArgsConstructor
public class MemberRepository {
// 의존성 주입 어노테이션
private final EntityManager em; // 롬복을 통해 생성자 생성
@Autowired
public void setMemberRepository(MemberRepository memberRepository) { // setter 인젝션
this.memberRepository = memberRepository;
}
@RequiredArgsConstructor // 롬복을 통해 생성자 생성
public class MemberService {
private final MemberRepository memberRepository; // 생성 시점 외 변경할 필요가 없기에 final
@Service
@Transactional(readOnly = true)
// JPA의 모든 로직은 트랜잭션 안에서 실행 되어야 한다.
// readOnly 걸면 조회 최적화, 더티체킹 안하고 뭐 그럼 읽기가 더 많다면 클래스 레벨 트랜잭션 걸어도 됨
@RequiredArgsConstructor // 롬복을 통해 생성자 생성
public class MemberService {
private final MemberRepository memberRepository; // 생성 시점 외 변경할 필요가 없기에 final
// 회원 가입
@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.getUsername());
if (!findMembers.isEmpty()) {
throw new IllegalStateException("이미 존재 하는 회원");
}
}
// 회원 전체 조회
public List<Member> findMembers() {
return memberRepository.findAll();
}
// 회원 단건 조회
public Member findOne(Long memberId) {
return memberRepository.findOne(memberId);
}
}