Skip to content

Commit e65fc7d

Browse files
committed
fix: return boolean for exists queries instead of throwing ClassCastException (#622)
Both RediSearchQuery and RedisEnhancedQuery were returning entity objects for existsBy* query methods, causing ClassCastException when the repository method expected a boolean return type. Modified executeQuery methods in both query classes to detect when the return type is boolean/Boolean and return the result of checking if any documents were found (searchResult.getTotalResults() > 0) instead of attempting to return the entity object. Added tests to verify existsBy* methods work correctly for both @document and @RedisHash entities.
1 parent d474dec commit e65fc7d

File tree

4 files changed

+62
-2
lines changed

4 files changed

+62
-2
lines changed

redis-om-spring/src/main/java/com/redis/om/spring/repository/query/RediSearchQuery.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,12 @@ private Object executeQuery(Object[] parameters) {
677677
// what to return
678678
Object result = null;
679679

680-
if (queryMethod.getReturnedObjectType() == SearchResult.class) {
680+
// Check if this is an exists query
681+
if (processor.getReturnedType().getReturnedType() == boolean.class || processor.getReturnedType()
682+
.getReturnedType() == Boolean.class) {
683+
// For exists queries, return true if we have any results, false otherwise
684+
result = searchResult.getTotalResults() > 0;
685+
} else if (queryMethod.getReturnedObjectType() == SearchResult.class) {
681686
result = searchResult;
682687
} else if (queryMethod.isPageQuery()) {
683688
List<Object> content = searchResult.getDocuments().stream().map(this::parseDocumentResult).toList();

redis-om-spring/src/main/java/com/redis/om/spring/repository/query/RedisEnhancedQuery.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,12 @@ private Object executeQuery(Object[] parameters) {
577577
// what to return
578578
Object result;
579579

580-
if (queryMethod.getReturnedObjectType() == SearchResult.class) {
580+
// Check if this is an exists query
581+
if (processor.getReturnedType().getReturnedType() == boolean.class || processor.getReturnedType()
582+
.getReturnedType() == Boolean.class) {
583+
// For exists queries, return true if we have any results, false otherwise
584+
result = searchResult.getTotalResults() > 0;
585+
} else if (queryMethod.getReturnedObjectType() == SearchResult.class) {
581586
result = searchResult;
582587
} else if (queryMethod.isPageQuery()) {
583588
List<Object> content = searchResult.getDocuments().stream().map(d -> {

tests/src/test/java/com/redis/om/spring/annotations/document/BasicRedisDocumentMappingTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,4 +916,23 @@ void testEffectOfNotNullAnnotation() {
916916
assertThat(fields).hasSize(1);
917917
assertThat(fields).first().isEqualTo("001");
918918
}
919+
920+
@Test
921+
void testIssue622_ExistsByQueryReturnsBoolean() {
922+
// Test for issue #622: existsBy* queries should return boolean instead of throwing ClassCastException
923+
Company redis = Company.of("RedisInc", 2011, LocalDate.of(2021, 5, 1),
924+
new Point(-122.066540, 37.377690), "[email protected]");
925+
repository.save(redis);
926+
927+
// Test exists query returns true for existing email
928+
boolean exists = repository.existsByEmail("[email protected]");
929+
assertTrue(exists, "Should return true for existing email");
930+
931+
// Test exists query returns false for non-existing email
932+
boolean notExists = repository.existsByEmail("[email protected]");
933+
assertFalse(notExists, "Should return false for non-existing email");
934+
935+
// Clean up
936+
repository.delete(redis);
937+
}
919938
}

tests/src/test/java/com/redis/om/spring/annotations/hash/BasicRedisHashMappingTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,4 +756,35 @@ void testRepositoryGetKeyFor() {
756756
assertThat(redisKey).isEqualTo(getKey(Company.class.getName(), redis.getId()));
757757
assertThat(microsoftKey).isEqualTo(getKey(Company.class.getName(), microsoft.getId()));
758758
}
759+
760+
@Test
761+
void testIssue622_HashExistsByQueryReturnsBoolean() {
762+
// Test for issue #622: existsBy* queries should return boolean for hash entities
763+
Person john = new Person();
764+
john.setName("John Doe");
765+
john.setEmail("[email protected]");
766+
john.setNickname("johnd");
767+
john.setRoles(Set.of("admin"));
768+
john.setFavoriteFoods(Set.of("pizza"));
769+
personRepo.save(john);
770+
771+
// Test exists query returns true for existing email
772+
boolean existsByEmail = personRepo.existsByEmail("[email protected]");
773+
assertTrue(existsByEmail, "Should return true for existing email");
774+
775+
// Test exists query returns true for existing nickname
776+
boolean existsByNickname = personRepo.existsByNickname("johnd");
777+
assertTrue(existsByNickname, "Should return true for existing nickname");
778+
779+
// Test exists query returns false for non-existing email
780+
boolean notExistsByEmail = personRepo.existsByEmail("[email protected]");
781+
assertFalse(notExistsByEmail, "Should return false for non-existing email");
782+
783+
// Test exists query returns false for non-existing nickname
784+
boolean notExistsByNickname = personRepo.existsByNickname("nonexisting");
785+
assertFalse(notExistsByNickname, "Should return false for non-existing nickname");
786+
787+
// Clean up
788+
personRepo.delete(john);
789+
}
759790
}

0 commit comments

Comments
 (0)