package study.datajpa.repository;
import org.springframework.stereotype.Repository;
import study.datajpa.entity.Member;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
import java.util.Optional;
@Repository
public class MemberJpaRepository {
@PersistenceContext
private EntityManager em;
public Member save(Member member) {
em.persist(member);
return member;
}
public void delete(Member member) {
em.remove(member);
}
public List<Member> findAll() {
return em.createQuery("select m from Member m", Member.class)
.getResultList();
}
public Optional<Member> findById(Long id) {
Member member = em.find(Member.class, id);
return Optional.ofNullable(member);
}
public long count() {
return em.createQuery("select count(m) from Member m", Long.class)
.getSingleResult();
}
public Member find(Long id) {
return em.find(Member.class, id);
}
}
package study.datajpa.repository;
import org.springframework.stereotype.Repository;
import study.datajpa.entity.Member;
import study.datajpa.entity.Team;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
import java.util.Optional;
@Repository
public class TeamRepository {
@PersistenceContext
EntityManager em;
public Team save(Team team) {
em.persist(team);
return team;
}
public void delete(Team team) {
em.remove(team);
}
public List<Team> findAll() {
return em.createQuery("select t from Team t",Team.class)
.getResultList();
}
public Optional<Team> findById(Long id) {
Team team = em.find(Team.class, id);
return Optional.ofNullable(team);
}
public long count() {
return em.createQuery("select count(t) from Team t", Long.class)
.getSingleResult();
}
}
어떻게 이렇게만 설정해도 save(), delete()
등등 메서드가 알아서 동작하는 걸까?
그건 바로 이 JpaRepository
가 프록시로 들어가서 그렇다.
프록시로 동작하기 때문에 구현된 클래스가 들어가게 되어, 동작하게 된다는 것.
@Repository
어노테이션 생략 가능이전에 사용했던 리포지토리 테스트 그대로 가져와서 하면 통과된다.
기능이 잘 동작한다는 것이 확인됨.
T findOne(ID)
-> Optional<T> findById(ID)
변경
제네릭 타입
T
: 엔티티ID
: 엔티티의 식별자 타입S
: 엔티티와 그 자식 타입주요 메서드
save(S)
: 새로운 엔티티는 저장하고 이미 있는 엔티티는 병합한다.delete(T)
: 엔티티 하나를 삭제한다. 내부에서 EntityManager.remove()
호출findById(ID)
: 엔티티 하나를 조회한다. 내부에서 EntityManager.find()
호출getOne(ID)
: 엔티티를 프록시로 조회한다. 내부에서 EntityManager.getReference()
호출findAll(...)
: 모든 엔티티를 조회한다. 정렬(Sort
)이나 페이징(Pageable
)조건을 파라미터로 제공할 수 있다.이러한 공통 메서드를 제공한다.
그런데 특정한 메서드를 더 디테일하게 만들고 싶을때 이를 구현하기가 쉽지 않다. 예를 들어 유저이름(username
)으로 엔티티(Member
)를 조회하고 싶을때,
이 리포지토리를 상속받아서 구현하기에는 너무나도 많은 양의 메서드가 들어있어서 구현이 불가능하다.
이를 가능하게 하는 방법이 있고, 최종본으로는 커스텀 기능이라는 것이 있다.
이 커스텀 기능은 맨 나중에 배우게 되고,
이제 곧 배울건 그냥 메서드 구현을 할 수 있는 방법에 대해서이다.