diff --git a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQuery.java b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQuery.java index 7f41b564..a8543801 100644 --- a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQuery.java +++ b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQuery.java @@ -15,6 +15,7 @@ */ package org.springframework.data.jdbc.repository.support; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.jdbc.core.RowMapper; @@ -53,7 +54,15 @@ class JdbcRepositoryQuery implements RepositoryQuery { parameters.addValue(parameterName, objects[p.getIndex()]); }); - return context.getTemplate().query(query, parameters, rowMapper); + if (queryMethod.isCollectionQuery() || queryMethod.isStreamQuery()) { + return context.getTemplate().query(query, parameters, rowMapper); + } else { + try { + return context.getTemplate().queryForObject(query, parameters, rowMapper); + } catch (EmptyResultDataAccessException e) { + return null; + } + } } @Override diff --git a/src/test/java/org/springframework/data/jdbc/repository/query/QueryAnnotationHsqlIntegrationTests.java b/src/test/java/org/springframework/data/jdbc/repository/query/QueryAnnotationHsqlIntegrationTests.java index 2bf27cd2..9f71164d 100644 --- a/src/test/java/org/springframework/data/jdbc/repository/query/QueryAnnotationHsqlIntegrationTests.java +++ b/src/test/java/org/springframework/data/jdbc/repository/query/QueryAnnotationHsqlIntegrationTests.java @@ -18,6 +18,8 @@ package org.springframework.data.jdbc.repository.query; import static org.assertj.core.api.Assertions.*; import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; import org.junit.ClassRule; import org.junit.Rule; @@ -80,6 +82,57 @@ public class QueryAnnotationHsqlIntegrationTests { } + @Test // DATAJDBC-172 + public void executeCustomQueryWithReturnTypeIsOptional() { + + DummyEntity dummyEntity = dummyEntity("a"); + repository.save(dummyEntity); + + Optional entity = repository.findByIdWithReturnTypeIsOptional(dummyEntity.id); + + assertThat(entity).map(e -> e.name).contains("a"); + + } + + @Test // DATAJDBC-172 + public void executeCustomQueryWithReturnTypeIsOptionalWhenEntityNotFound() { + + DummyEntity dummyEntity = dummyEntity("a"); + repository.save(dummyEntity); + + Optional entity = repository.findByIdWithReturnTypeIsOptional(9999L); + + assertThat(entity).isNotPresent(); + + } + + @Test // DATAJDBC-172 + public void executeCustomQueryWithReturnTypeIsEntity() { + + DummyEntity dummyEntity = dummyEntity("a"); + repository.save(dummyEntity); + + DummyEntity entity = repository.findByIdWithReturnTypeIsEntity(dummyEntity.id); + + assertThat(entity).isNotNull(); + assertThat(entity.name).isEqualTo("a"); + + } + + @Test // DATAJDBC-172 + public void executeCustomQueryWithReturnTypeIsStream() { + + repository.save(dummyEntity("a")); + repository.save(dummyEntity("b")); + + Stream entities = repository.findAllWithReturnTypeIsStream(); + + assertThat(entities) // + .extracting(e -> e.name) // + .containsExactlyInAnyOrder("a", "b"); + + } + private DummyEntity dummyEntity(String name) { DummyEntity entity = new DummyEntity(); @@ -110,8 +163,17 @@ public class QueryAnnotationHsqlIntegrationTests { @Query("SELECT * FROM DUMMYENTITY WHERE lower(name) <> name") List findByNameContainingCapitalLetter(); - @Query("SELECT * FROM DUMMYENTITY WHERE name < :upper and name > :lower") List findByNamedRangeWithNamedParameter(@Param("lower") String lower, @Param("upper") String upper); + + @Query("SELECT * FROM DUMMYENTITY WHERE id = :id FOR UPDATE") + Optional findByIdWithReturnTypeIsOptional(@Param("id") Long id); + + @Query("SELECT * FROM DUMMYENTITY WHERE id = :id FOR UPDATE") + DummyEntity findByIdWithReturnTypeIsEntity(@Param("id") Long id); + + @Query("SELECT * FROM DUMMYENTITY") + Stream findAllWithReturnTypeIsStream(); + } }