<aside> 💡 Java 및 Spring Framework에서 어노테이션이 붙은 클래스가 데이터 엑세스 및 지속성 작업을 담당하는 저장소임을 나타내는데 사용되는 주석
</aside>
@Repository
public class MemberRepository {
@PersistenceContext // JPA EntityManager를 주입해준다.
private EntityManager em;
// 만약 EntityManagerFactory를 직접 제어하고 싶다면??
// @PersistenceUnit private EntityManagerFactory emf;
public void save(Member member) {
em.persist(member); // 영속성 컨텍스트에 넣기
}
// 1개 조회
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(readOnly = true)
// 조회는 readOnly = true 설정해서 성능 향상 (데이터 변경이 안된다)
public class MemberService {
@Autowired
private MemberRepository memberRepository;
// 회원 가입 (성공시 id를 반환한다.)
@Transactional
public Long join(Member member) {
validateDuplicateMember(member); // 중복 회원 검증
memberRepository.save(member);
return member.getId();
}
// DB에 동시에 insert 하면 ?...
// 최후의 방어를 위해서 memberName을 unique 제약 조건으로 걸어주는 방법 있다.
private void validateDuplicateMember(Member member) {
List<Member> findMembers = memberRepository.findByName(member.getName());
if (!findMembers.isEmpty()) {
throw new IllegalStateException("이미 존재하는 회원입니다.");
}
}
// 회원 전체 조회
private List<Member> findMembers() {
return memberRepository.findAll();
}
private Member findOne(Long memberId) {
return memberRepository.findOne(memberId);
}
}
필드 Injection (주입하기 까다롭다)
setter Injection (주입하기 좋지만, Runtime 시점에 누군가가바꿔치기 할 수 있다. 그럴가능성이 적겠지만)
생성자 Injection (주입하기 좋고, 값을 세팅안하면 컴파일 에러를 통해 명확하게 알 수 있다.)
(생성자 Injection → 롬복 → @RequiredArgsConstructor) 아래의 생성자 주입을 롬복으로 대체하길 권장한다고 한다.
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@PersistenceContext
private EntityManager em;
// 이거 역시 생성자 주입 방식으로 변경할 수 있다. (내부적으로 Spring JPA가 주입해준다.)
@RequiredArgsConstructor
public ~~~ {
private final EntityManager em;
}
cmd + shift + T : 테스트 코드 자동 생성