Skip to content

Commit

Permalink
CCMSPUI-383 Refactored CaseSearchRepository to use EntityManager inst…
Browse files Browse the repository at this point in the history
…ead to search for cases to return results quicker

Signed-off-by: Jamie Briggs <[email protected]>
  • Loading branch information
JamieBriggs-MoJ committed Jan 14, 2025
1 parent 060799e commit 8fe1774
Show file tree
Hide file tree
Showing 18 changed files with 285 additions and 285 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void shouldGetAllNotifications(){
null,
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(2, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -98,7 +98,7 @@ void shouldFilterByCaseReferenceNumber(){
null,
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(1, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -119,7 +119,7 @@ void shouldFilterBySimilarCaseReferenceNumber(){
null,
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(2, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -141,7 +141,7 @@ void shouldFilterByProviderCaseReferenceNumber(){
null,
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(1, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -162,7 +162,7 @@ void shouldFilterBySimilarProviderCaseReferenceNumber(){
null,
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(2, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -184,7 +184,7 @@ void shouldFilterByAssignedToUserID(){
null,
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(1, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -205,7 +205,7 @@ void shouldFilterByUserSurname(){
null,
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(1, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -226,7 +226,7 @@ void shouldFilterByLikeUserSurname(){
null,
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(2, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -248,7 +248,7 @@ void shouldFilterByFeeEarnerID(){
null,
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(1, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -268,7 +268,7 @@ void shouldFilterByNotificationType(){
null,
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(1, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -289,7 +289,7 @@ void shouldFilterByDateFrom(){
LocalDate.of(2025, 2, 1),
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(1, result.getTotalElements());
assertEquals(true, result.getContent().contains(n2));
Expand All @@ -310,7 +310,7 @@ void shouldFilterByDateFromInclusive(){
LocalDate.of(2024, 1, 1),
null);
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(2, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -332,7 +332,7 @@ void shouldFilterByDateTo(){
null,
LocalDate.of(2025, 12, 1));
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(1, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand All @@ -353,7 +353,7 @@ void shouldFilterByDateToInclusive(){
null,
LocalDate.of(2026, 1, 1));
// When
Page<Notification> result = notificationRepository.findAll(spec, Pageable.unpaged());
Page<Notification> result = notificationRepository.findAll(spec, Pageable.ofSize(10).withPage(0));
// Then
assertEquals(2, result.getTotalElements());
assertEquals(true, result.getContent().contains(n1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void testGetProceedings() {

// Call the service method
ProceedingDetails result = proceedingService.getProceedings(
categoryOfLawCode, null, null, null, Pageable.unpaged());
categoryOfLawCode, null, null, null, Pageable.ofSize(10).withPage(0));

// Assert the proceeding
assertNotNull(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void testGetScopeLimitations_MultiMatch() {

// Call the service method
ScopeLimitationDetails result = scopeLimitationService.getScopeLimitations(
scopeLimitationDetail, Pageable.unpaged());
scopeLimitationDetail, Pageable.ofSize(10).withPage(0));

// Assert the proceeding
assertNotNull(result);
Expand Down Expand Up @@ -88,7 +88,7 @@ public void testGetScopeLimitations_SingleMatch() {

// Call the service method
ScopeLimitationDetails result = scopeLimitationService.getScopeLimitations(
scopeLimitationDetail, Pageable.unpaged());
scopeLimitationDetail, Pageable.ofSize(10).withPage(0));

// Assert the proceeding
assertNotNull(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public void testGetUser_noData(){
"11, 1",
"12, 0"})
public void testGetUsers_returnsData(Integer providerId, int expectedElements){
UserDetails userDetails = userService.getUsers(providerId, Pageable.unpaged());
UserDetails userDetails = userService.getUsers(providerId, Pageable.ofSize(10).withPage(0));
assertNotNull(userDetails);
assertEquals(expectedElements, userDetails.getTotalElements());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,124 @@
package uk.gov.laa.ccms.data.repository;

import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import uk.gov.laa.ccms.data.entity.CaseSearch;

/**
* Repository interface for accessing {@link CaseSearch} entities.
* A repository class for performing search queries on {@link CaseSearch} entities.
*
* <p>This repository extends the {@link ReadOnlyRepository} interface,
* it supports read-only operations for the {@link CaseSearch} entity.
* This repository also extends {@link JpaSpecificationExecutor}, which
* allows the use of {@link org.springframework.data.jpa.domain.Specification}
* to filter easier.</p>
* <p>This class utilizes a native SQL query to fetch filtered and paginated results
* from the <b>XXCCMS_CASE_SEARCH_V</b> database view. It combines filtering criteria such
* as provider firm party ID, case references, case status, client surname, fee earner ID, and
* provider office party ID to dynamically construct the query based on the passed parameters.</p>
*
* <p>It relies on {@link EntityManager} to execute native SQL queries and doesn't use standard
* Spring Data repositories. All queries are read-only and do not modify the database state.</p>
*
* @see Page
* @see CaseSearch
* @see ReadOnlyRepository
* @see org.springframework.data.jpa.domain.Specification
* @see EntityManager
*
* @author Jamie Briggs
*/
@Repository
public interface CaseSearchRepository extends ReadOnlyRepository<CaseSearch, Long>,
JpaSpecificationExecutor<CaseSearch> {
@Component
@RequiredArgsConstructor
public class CaseSearchRepository {

private final EntityManager entityManager;

/**
* Retrieves a paginated and filtered list of case search records based on the given parameters.
*
* @param providerFirmPartyId the unique identifier of the provider firm (mandatory)
* @param caseReferenceNumber the case reference number for filtering, can be partially matched
* @param providerCaseReference the reference number specific to the provider for filtering
* @param caseStatus the status of the case to filter by
* @param clientSurname the surname of the client to filter by; case-insensitive partial
* matches are allowed
* @param feeEarnerId the unique identifier of the associated fee earner to filter by
* @param officeId the unique identifier of the provider's office to filter by
* @param pageable the pagination and sorting information
* @return a paginated list of {@code CaseSearch} entities matching the filtering criteria
*/
@Transactional(readOnly = true)
public Page<CaseSearch> findAll(final long providerFirmPartyId, final String caseReferenceNumber,
final String providerCaseReference, final String caseStatus, final String clientSurname,
final Long feeEarnerId, final Long officeId, final Pageable pageable) {

final String searchCaseQuery =
"""
SELECT * FROM XXCCMS_CASE_SEARCH_V
"""
+
getFilterSql(providerFirmPartyId, caseReferenceNumber, providerCaseReference, caseStatus,
clientSurname, feeEarnerId, officeId)
+
"""
OFFSET :offset ROWS FETCH NEXT :size ROWS ONLY
""";

Query query = entityManager.createNativeQuery(searchCaseQuery, CaseSearch.class);
query.setHint("org.hibernate.readOnly", true);
query.setParameter("offset", pageable.getOffset());
query.setParameter("size", pageable.getPageSize());

final String countCaseQuery =
"""
SELECT COUNT(*) FROM XXCCMS_CASE_SEARCH_V
"""
+ getFilterSql(providerFirmPartyId, caseReferenceNumber, providerCaseReference,
caseStatus, clientSurname, feeEarnerId, officeId);
Query countQuery = entityManager.createNativeQuery(countCaseQuery);

countQuery.setHint("org.hibernate.readOnly", true);
long total = ((Number) countQuery.getSingleResult()).longValue();

List<CaseSearch> resultList = query.getResultList();

return new PageImpl<>(resultList, pageable, total);
}

private static String getFilterSql(long providerFirmPartyId, String caseReferenceNumber,
String providerCaseReference, String caseStatus, String clientSurname, Long feeEarnerId,
Long officeId) {
StringJoiner sj = new StringJoiner(" AND ");
// Provider firm party id
sj.add("WHERE PROVIDER_FIRM_PARTY_ID = " + providerFirmPartyId);
// Case reference number
if (!Objects.isNull(caseReferenceNumber) && !caseReferenceNumber.isBlank()) {
sj.add("LSC_CASE_REFERENCE LIKE '%" + caseReferenceNumber + "%'");
}
// Provider case reference
if (!Objects.isNull(providerCaseReference) && !providerCaseReference.isBlank()) {
sj.add("CIS_CASE_REFERENCE LIKE '%" + providerCaseReference + "%'");
}
// Case status
if (!Objects.isNull(caseStatus) && !caseStatus.isBlank()) {
sj.add("ACTUAL_CASE_STATUS = '" + caseStatus + "'");
}
// Surname
if (!Objects.isNull(clientSurname) && !clientSurname.isBlank()) {
sj.add("UPPER(PERSON_LAST_NAME) LIKE '%" + clientSurname.toUpperCase() + "%'");
}
// Fee earner party ID
if (!Objects.isNull(feeEarnerId)) {
sj.add("FEE_EARNER_PARTY_ID = " + feeEarnerId);
}
// Provider office party ID
if (!Objects.isNull(officeId)) {
sj.add("PROVIDER_OFFICE_PARTY_ID = " + officeId);
}
return sj + " ";
}

}
Loading

0 comments on commit 8fe1774

Please sign in to comment.