만드는 순서를 자꾸 까먹어서 정리를 해 놓겠다.
1. 만들고자 하는 메서드를 정의한 [인터페이스]를 새로 생성!
//사용자 정의 인터페이스 with Spring Data JPA
public interface MemberRepositoryCustom {
// select condition에 따른 [동적] 쿼리 구현
List<MemberTeamDto> search(MemberSearchCondition condition);
}
2. 인터페이스에서 정의한 메서드를 오버라이딩
-> 구현 클래스의 이름에 주의해야 한다. [원조 인터페이스 명] + [Impl]과 같이 앞에 MemberRepository 인터페이스 명을 붙여줘야 한다.
@Repository
public class MemberRepositoryImpl implements MemberRepositoryCustom{
private final JPAQueryFactory queryFactory;
//생성자가 1개일 떈, 자동으로 @Autowired가 붙는다
public MemberRepositoryImpl(EntityManager entityManager){
this.queryFactory = new JPAQueryFactory(entityManager);
}
@Override
// Where절에 다중 파라미터로 [동적] 쿼리 구현
public List<MemberTeamDto> search(MemberSearchCondition condition) {
return queryFactory
.select(new QMemberTeamDto(
member.id,
member.username,
member.age,
team.id,
team.name))
.from(member)
.leftJoin(member.team, team)
.where(
usernameEq(condition.getUsername()),
teamNameEq(condition.getTeamName()),
ageGoe(condition.getAgeGoe()),
ageLoe(condition.getAgeLoe()))
.fetch();
}
private BooleanExpression ageLoe(Integer ageLoe) {
return ageLoe == null ? null : member.age.loe(ageLoe);
}
private BooleanExpression ageGoe(Integer ageGoe) {
return ageGoe == null ? null : member.age.goe(ageGoe);
}
private BooleanExpression teamNameEq(String teamName) {
return isEmpty(teamName) ? null : team.name.eq(teamName);
}
private BooleanExpression usernameEq(String username) {
return isEmpty(username) ? null : member.username.eq(username);
}
3. MemberRepisotryCustom [인터페이스]를 MemberRepository [인터페이스]가 상속받게 한다.
public interface MemberRepository extends JpaRepository<Member,Long>, MemberRepositoryCustom {
// 인터페이스는 다중 상속 가능!
List<Member> findByUsername(String username); // == "select m from Member m Where username = :username"([정적] 쿼리)
}
주제와는 상관이 없지만, 만약에 이 쿼리가 매우 특수하고 공용성이 없는 쿼리라면, 사용자 정의 인터페이스로 구현하기 보
다는, 따로 Repository를 만들어서 사용하는 것이 낫다.
핵심 비지니스 로직이나 공용성이 높고 하는 쿼리들과 그렇지 않은 특수하고 공용성이 없는 쿼리들은 서로 수정하는
라이프사이클이 다르다.
그래서, 아키텍처 설계 측면에서 이러한 것들을 분리해서 설계하는 것이 좋다.
ex)
-> search() 메서드를 MemberQueryRepository 클래스에 별도로 구현해 놓음.
범용성이 있고, 핵심 비지니스 로직 같은 경우에는 Spring Data JPA에서 제공하는 사용자 정의 인터페이스를 사용하여
정의하는 것이 맞다.
'CS 잡지식' 카테고리의 다른 글
반응형 웹(Feat. boot strap) (0) | 2023.06.02 |
---|---|
JS 기본(Feat.JS 코드는 <body>젤 밑에 적자) (0) | 2023.06.02 |
동적(dynamic) 쿼리 vs 정적(static) 쿼리 (0) | 2023.05.19 |
연관 관계 세팅 TIP!!! (0) | 2023.05.19 |
샘플 데이터 입력의 2가지 방법 (0) | 2023.05.19 |