2024. 10. 20. 19:18ㆍSpring Boot/Spring Data JPA
Other Methods
Spring Data JPA는 다양한 방법으로 쿼리를 작성할 수 있는 기능을 제공합니다. 그러나 때때로 쿼리가 제공된 기술로는 너무 복잡할 수 있습니다. 이런 경우에는 다음과 같은 대안들을 고려해볼 수 있습니다.
1. 직접 쿼리 작성하기
가장 먼저 고려해야 할 방법은 @Query
어노테이션을 사용하여 직접 쿼리를 작성하는 것입니다. 이를 통해 JPQL, HQL, 또는 네이티브 SQL을 사용하여 원하는 대로 쿼리를 구성할 수 있습니다.
예를 들어:
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE u.lastname = ?1")
List<User> findByLastname(String lastname);
}
이와 같이 쿼리를 직접 작성하면, 쿼리가 복잡하더라도 원하는 결과를 얻을 수 있습니다.
2. 커스텀 구현체 만들기
직접 쿼리를 작성하는 것이 충분하지 않거나 더 복잡한 로직이 필요한 경우, 커스텀 구현을 고려할 수 있습니다. 이를 통해 레포지토리에 메서드를 등록하면서 구현은 전적으로 사용자에게 맡길 수 있습니다.
이렇게 하면 다음과 같은 기능을 활용할 수 있습니다:
- EntityManager 직접 사용: 순수 HQL, JPQL, EQL, 네이티브 SQL을 작성하거나 Criteria API를 사용할 수 있습니다.
- Spring Framework의 JdbcTemplate 활용: 네이티브 SQL을 작성하여 데이터베이스와 직접 상호작용할 수 있습니다.
- 타사 데이터베이스 툴킷 사용: 특정 데이터베이스나 ORM에 특화된 툴킷을 사용할 수 있습니다.
예를 들어, 커스텀 리포지토리 구현을 통해 복잡한 쿼리를 작성할 수 있습니다:
public class UserRepositoryImpl implements UserRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<User> customQueryMethod() {
String jpql = "SELECT u FROM User u WHERE u.age > :age";
return entityManager.createQuery(jpql, User.class)
.setParameter("age", 18)
.getResultList();
}
}
3. 데이터베이스 내장 쿼리 사용하기
쿼리를 데이터베이스에 저장하고 싶다면, @StoredProcedure
어노테이션을 사용하여 저장 프로시저를 호출하거나, 데이터베이스 함수에 대해 @Query
어노테이션을 사용하고 CALL
로 호출할 수 있습니다.
예를 들어, 저장 프로시저를 호출하는 방법은 다음과 같습니다:
public interface UserRepository extends JpaRepository<User, Long> {
@Modifying
@Procedure(name = "my_procedure")
void callMyProcedure();
}
이러한 방법들은 최대한의 쿼리 제어를 필요로 할 때 유용하며, Spring Data JPA가 제공하는 자원 관리 기능을 유지하면서도 더 복잡한 로직을 구현할 수 있게 해줍니다. 각 방법의 사용은 필요에 따라 선택할 수 있으며, 복잡한 쿼리 로직을 요구하는 비즈니스 요구사항에 맞게 조정할 수 있습니다.
Modifying Queries
Spring Data JPA는 쿼리를 선언하여 엔티티나 엔티티 컬렉션에 접근하는 방법을 설명했습니다. 이제는 쿼리를 수정하는 사용자 정의 동작을 추가할 수 있는 방법에 대해 알아보겠습니다.
1. 수정 쿼리 선언하기
수정 쿼리는 특정 엔티티의 속성을 업데이트하거나 삭제하는 쿼리입니다. 이를 위해 @Modifying
어노테이션을 사용해야 합니다. 다음은 수정 쿼리의 예시입니다:
@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);
이와 같이 @Modifying
을 사용하면 해당 쿼리가 선택 쿼리(selecting query)가 아닌 업데이트 쿼리로 처리됩니다.
2. EntityManager와의 관계
수정 쿼리를 실행한 후에는 EntityManager
가 오래된 엔티티를 포함할 수 있습니다. Spring Data JPA는 EntityManager.clear()
를 자동으로 호출하지 않습니다. 이는 여전히 플러시되지 않은 변경 사항을 모두 삭제하기 때문입니다. 만약 EntityManager
를 자동으로 지우고 싶다면, @Modifying
어노테이션의 clearAutomatically
속성을 true
로 설정할 수 있습니다.
3. 파생 삭제 쿼리
Spring Data JPA는 파생 삭제 쿼리를 지원하여 JPQL 쿼리를 명시적으로 선언하지 않고도 삭제 작업을 수행할 수 있습니다. 다음은 파생 삭제 쿼리의 예입니다:
interface UserRepository extends Repository<User, Long> {
void deleteByRoleId(long roleId);
@Modifying
@Query("delete from User u where u.role.id = ?1")
void deleteInBulkByRoleId(long roleId);
}
deleteByRoleId(long roleId)
메서드는 기본적으로 deleteInBulkByRoleId(long roleId)
와 유사한 결과를 생성하는 것처럼 보입니다. 그러나 두 메서드 선언 사이에는 중요한 차이가 있습니다.
deleteInBulkByRoleId(...)
메서드는 주어진 JPQL 쿼리를 데이터베이스에 단일 쿼리로 발행합니다. 이로 인해 현재 로드된User
인스턴스는 생명주기 콜백(lifecycle callbacks)을 호출하지 않습니다.- 반면에
deleteByRoleId(...)
는 쿼리를 실행한 후 결과를 하나씩 삭제하여 영속성 제공자가 해당 엔티티에서@PreRemove
콜백을 실제로 호출할 수 있도록 합니다.
파생 삭제 쿼리는 쿼리를 실행한 후 CrudRepository.delete(Iterable users) 메서드를 호출하여 엔티티를 삭제하는 방법의 단축키 역할을 합니다. 이를 통해 CRUD 연산의 일관성을 유지하면서 더 간결하게 쿼리를 작성할 수 있습니다. 수정 쿼리와 삭제 쿼리를 효과적으로 활용하면, 복잡한 비즈니스 로직을 간단하게 처리할 수 있습니다.
'Spring Boot > Spring Data JPA' 카테고리의 다른 글
Configuring Fetch- and LoadGraphs (0) | 2024.10.20 |
---|---|
Applying Query Hints (0) | 2024.10.20 |
Using Sort, Scrolling Large Query Results (0) | 2024.10.20 |
Using @Query (0) | 2024.10.20 |
Using JPA Named Queries (0) | 2024.10.20 |