Spring Data JPA, QueryDSL, EntityManager를 쓰면서 실수 한 것들도 있었고 이거는 좀 괜찮은데? 라고 생각한 것들도 있었다, 실수를 줄이고 팁들을 공유하기위해 작성하기로 했다.
프로젝트를 진행하다가 기본적인 CRUD를 작성하자니 생산성이 떨어져 그냥 QueryDSL와 JPARepository를 같이 쓰면 어떨까? 라는 생각에서 찾아보니 방법이 간단했다.
간단히 기존의 인터페이스에 JPARepository, QueryDSL가 적용되어있는 인터페이스를 상속시켜주면 된다.
// JpaRepository : Spring Data JPA
// boardRepositoryCustom : QueryDSL을 사용하고 있는 인터페이스
@Repository
public interface boardRepository extends JpaRepository<Board, Integer>, boardRepositoryCustom{
}
이렇게 작성하면 JPARepository와 QueryDSL을 동시에 사용하면서 SOLID규칙 중 DIP를 준수할 수 있다.
사이드 프로젝트를 하면서 Spring Data JPA에 커스텀 메서드를 만들어야하는 경우가 있었는데 딱히 기능에 문제는 없어 보였지만 계속 컴파일 에러가 났다.
뭐라고 막 써있는데 likeRepository에서 문제가 났다고 한다, 하지만 거기에 있는 거는 JPARepository를 확장한 것과 커스텀으로 만든 메서드만 존재해서 처음에는 이상함을 느끼지 못했다, 그러다가 혹시 이름에 문제가 있는게 아닐까 싶어서 확인해보니 JPARepository를 추가하고 Keyword규칙기반으로 이름을 작성하니 정상적으로 동작하는 것을 확인했다.
그래서 기존에는 유저와 게시판하나를 선택하는 커스텀 메서드를 만들었는데 이렇게 이름을 지었었다.
@Repository
public interface likeRepository extends JpaRepository<Likes, Long>{
Optional<Likes> findByUserBoard(User user, Board board);
}
Keyword 규칙을 지키면서 이렇게 바꾸었다.
@Repository
public interface likeRepository extends JpaRepository<Likes, Long>{
Optional<Likes> findByUserAndBoard(User user, Board board);
}
사용 팁 1번을 사용하면서 생긴 문제였다, JPARepository와 QueryDSL을 동시에 사용하다가 Bean주입을 2개를 하고말아 우선순위가 꼬여서 생긴 컴파일 에러였다.
그래서 방법을 찾아보니 방법이 2가지가 있었다.
@Primary
방법을 사용하여 우선 순위를 지정하는 방법이고 다른 하나는 Bean의 이름을 다르게 지정하는 @Qualifier
를 사용하는 방법이 있었다,
타입당 주입을 받는 클래스가 2개 였기에 @Primary
방법을 사용했다. 하지만 @Primary
에 주의사항이 있다, 동일한 타입당 한 번만 사용해야한다.
@Repository
@Primary
public interface mainRepository extends JpaRepository<Test, Integer>, subRepository {
}
...
@Repository
public class subRepositoryImpl implements subRepository {
@Override
public String getManagerName() {
return "Department manager";
}
}