공통 인터페이스 기능
순수 JPA 기반 리포지토리 만들기
MemberJpaRepository
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);
}
}
TeamRepository
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();
}
}
Test
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
어노테이션 생략 가능- 컴포넌트 스캔을 스프링 데이터 JPA가 자동으로 처리
- JPA 예외를 스프링 예외로 변환하는 과정도 자동으로 처리
공통 인터페이스 적용
이전에 사용했던 리포지토리 테스트 그대로 가져와서 하면 통과된다.
기능이 잘 동작한다는 것이 확인됨.
공통 인터페이스 분석
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
)를 조회하고 싶을때,
이 리포지토리를 상속받아서 구현하기에는 너무나도 많은 양의 메서드가 들어있어서 구현이 불가능하다.
이를 가능하게 하는 방법이 있고, 최종본으로는 커스텀 기능이라는 것이 있다.
이 커스텀 기능은 맨 나중에 배우게 되고,
이제 곧 배울건 그냥 메서드 구현을 할 수 있는 방법에 대해서이다.
Author And Source
이 문제에 관하여(공통 인터페이스 기능), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@seungju0000/공통-인터페이스-기능저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)