JPA를 이용하면서 자동으로 쿼리를 만들어주는데, 어떻게 하면 JPA에서 like 조회를 진행하는지에 대해서 궁금해졌다.
이런저런 정보글들을 찾아보고, 실제로 적용이 되서 나온 경우를 몇가지 적겠다.
1. JpaRepository 이용, like 조회방법
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByUsernameContaining(String keyword);
}
컬럼명 + Containing 을 이용한다.
위 예제코드처럼 findByUsernameContaining 이라고 쓰고, 뒤에 받아올 키워드를 작성하면된다.
이를 이용해서 만약 키워드 자체가 없을땐 전체 조회, 키워드가 존재할경우 like 조회하는 방법을 controller에서는 다음과 같이 구현된다.
@Controller
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/users")
public String getUserList(Model model, @RequestParam(required = false) String keyword) {
List<User> userList;
if (keyword == null) {
userList = userRepository.findAll();
} else {
userList = userRepository.findByUsernameContaining(keyword);
}
model.addAttribute("userList", userList);
return "user_list";
}
}
만약 Entity가 @Embeded되어있는 상황이라면 어떻게 해야할까?
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByAddressCityContaining(String keyword);
}
물론 다 방법이 있다.
위와 같은 방식으로 사용한다면 Adress Entity의 Embeded된 City필드를 검색할 수 있다.
추가적으로 Containing 대신 Like라는것을 사용해도 된다.
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByNameLike(String keyword);
}
2. @Query 에서는 어떻게 가져올까?
마찬가지로 @Embeded된 데이터가 있다고 가정해보자.
@Query("SELECT p FROM Person p WHERE p.address.city LIKE %:city%")
List<Person> findPersonByCity(@Param("city") String city);
@Query방식은 참 쿼리 지향적이여서 내가 쿼리를 짜고 싶은대로 마음껏 표현이 가능하다.
위 에서는 Person Entity안에 있는 Embeded된 address 의 city컬럼을 가져올때 사용된 모습이다.
기본적으로는 저런 방식이 사용된다.
3. QueryDSL에서는 이렇게 사용한다.
String keyword = "foo";
BooleanBuilder builder = new BooleanBuilder();
builder.and(QEntity.entity.name.like("%" + keyword + "%"));
List<Entity> result = jpaQueryFactory.selectFrom(QEntity.entity)
.where(builder)
.fetch();
이게 뭔가 싶긴하지만, 간단하다.
querydsl에는 like() 을 지원한다. 이에 따라서 쉽게 구현이 가능하다.
(물론 %뿐만아니라 _도 사용이 가능하다.)