From 5f6a44d00a455a4608751ce05c7e92e9db3e59b9 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Fri, 9 Mar 2018 10:02:10 +0100 Subject: [PATCH] DATAJDBC-182 - Polishing. Extracted method to maintain a single level of abstraction. Added description to assertion that wasn't obvious to me. Added JavaDoc on existing method. Commented repository methods in test with issue ids to ease understanding the purpose of each method. --- .../support/JdbcQueryLookupStrategy.java | 25 ++++---- .../repository/support/JdbcQueryMethod.java | 7 +++ .../QueryAnnotationHsqlIntegrationTests.java | 59 +++++++++++-------- 3 files changed, 56 insertions(+), 35 deletions(-) diff --git a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java index 54842aea..ccc6039f 100644 --- a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java +++ b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java @@ -56,18 +56,21 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy { JdbcQueryMethod queryMethod = new JdbcQueryMethod(method, repositoryMetadata, projectionFactory); Class returnedObjectType = queryMethod.getReturnedObjectType(); - RowMapper rowMapper = null; - if (!queryMethod.isModifyingQuery()) { - rowMapper = context.getSimpleTypeHolder().isSimpleType(returnedObjectType) - ? SingleColumnRowMapper.newInstance(returnedObjectType, conversionService) - : new EntityRowMapper<>( // - context.getRequiredPersistentEntity(returnedObjectType), // - conversionService, // - context, // - accessStrategy // - ); - } + + RowMapper rowMapper = queryMethod.isModifyingQuery() ? null : createRowMapper(returnedObjectType); + return new JdbcRepositoryQuery(queryMethod, context, rowMapper); } + private RowMapper createRowMapper(Class returnedObjectType) { + + return context.getSimpleTypeHolder().isSimpleType(returnedObjectType) + ? SingleColumnRowMapper.newInstance(returnedObjectType, conversionService) + : new EntityRowMapper<>( // + context.getRequiredPersistentEntity(returnedObjectType), // + conversionService, // + context, // + accessStrategy // + ); + } } diff --git a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryMethod.java b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryMethod.java index dd2b3a26..ca748fe3 100644 --- a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryMethod.java +++ b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryMethod.java @@ -24,6 +24,7 @@ import org.springframework.data.jdbc.repository.query.Query; import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.query.QueryMethod; +import org.springframework.lang.Nullable; /** * {@link QueryMethod} implementation that implements a method by executing the query from a {@link Query} annotation on @@ -44,6 +45,12 @@ public class JdbcQueryMethod extends QueryMethod { this.method = method; } + /** + * Returns the annotated query if it exists. + * + * @return May be {@code null}. + */ + @Nullable public String getAnnotatedQuery() { Query queryAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, Query.class); 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 6f09adca..b227f7ab 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 @@ -15,6 +15,14 @@ */ package org.springframework.data.jdbc.repository.query; +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; @@ -33,14 +41,6 @@ import org.springframework.test.context.junit4.rules.SpringClassRule; import org.springframework.test.context.junit4.rules.SpringMethodRule; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDateTime; -import java.util.Date; -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.*; - /** * Tests the execution of queries from {@link Query} annotations on repository methods. * @@ -51,13 +51,10 @@ import static org.assertj.core.api.Assertions.*; @Transactional public class QueryAnnotationHsqlIntegrationTests { - @Autowired - DummyEntityRepository repository; + @Autowired DummyEntityRepository repository; - @ClassRule - public static final SpringClassRule classRule = new SpringClassRule(); - @Rule - public SpringMethodRule methodRule = new SpringMethodRule(); + @ClassRule public static final SpringClassRule classRule = new SpringClassRule(); + @Rule public SpringMethodRule methodRule = new SpringMethodRule(); @Test // DATAJDBC-164 public void executeCustomQueryWithoutParameter() { @@ -167,7 +164,7 @@ public class QueryAnnotationHsqlIntegrationTests { .containsExactlyInAnyOrder("a", "b"); } - + @Test // DATAJDBC-175 public void executeCustomQueryWithReturnTypeIsNubmer() { @@ -211,36 +208,40 @@ public class QueryAnnotationHsqlIntegrationTests { } @Test // DATAJDBC-182 - public void executeCustomModifyingQueryWithReturnTypeIsNumber() { + public void executeCustomModifyingQueryWithReturnTypeNumber() { DummyEntity entity = dummyEntity("a"); repository.save(entity); assertThat(repository.updateName(entity.id, "b")).isEqualTo(1); - assertThat(repository.updateName(9999L, "b")).isEqualTo(0); - assertThat(repository.findById(entity.id)).isPresent().map(e -> e.name).contains("b"); + assertThat(repository.updateName(9999L, "c")).isEqualTo(0); + assertThat(repository.findById(entity.id)) // + .describedAs("update was not performed as expected") // + .isPresent() // + .map(e -> e.name).contains("b"); } @Test // DATAJDBC-182 - public void executeCustomModifyingQueryWithReturnTypeIsBoolean() { + public void executeCustomModifyingQueryWithReturnTypeBoolean() { DummyEntity entity = dummyEntity("a"); repository.save(entity); assertThat(repository.deleteByName("a")).isTrue(); assertThat(repository.deleteByName("b")).isFalse(); - assertThat(repository.findById(entity.id)).isNotPresent(); + assertThat(repository.findById(entity.id)) // + .describedAs("delete not performed as expected") // + .isNotPresent(); } @Test // DATAJDBC-182 - public void executeCustomModifyingQueryWithReturnTypeIsVoid() { + public void executeCustomModifyingQueryWithReturnTypeVoid() { repository.insert("Spring Data JDBC"); assertThat(repository.findByNameAsEntity("Spring Data JDBC")).isNotNull(); - } private DummyEntity dummyEntity(String name) { @@ -263,49 +264,59 @@ public class QueryAnnotationHsqlIntegrationTests { private static class DummyEntity { - @Id - Long id; + @Id Long id; String name; } private interface DummyEntityRepository extends CrudRepository { + // DATAJDBC-164 @Query("SELECT * FROM DUMMYENTITY WHERE lower(name) <> name") List findByNameContainingCapitalLetter(); + // DATAJDBC-164 @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 name = :name") Optional findByNameAsOptional(@Param("name") String name); + // DATAJDBC-172 @Query("SELECT * FROM DUMMYENTITY WHERE name = :name") DummyEntity findByNameAsEntity(@Param("name") String name); + // DATAJDBC-172 @Query("SELECT * FROM DUMMYENTITY") Stream findAllWithReturnTypeIsStream(); + // DATAJDBC-175 @Query("SELECT count(*) FROM DUMMYENTITY WHERE name like '%' || :name || '%'") int countByNameContaining(@Param("name") String name); + // DATAJDBC-175 @Query("SELECT count(*) FROM DUMMYENTITY WHERE name like '%' || :name || '%'") boolean existsByNameContaining(@Param("name") String name); + // DATAJDBC-175 @Query("VALUES (current_timestamp)") Date nowWithDate(); + // DATAJDBC-175 @Query("VALUES (current_timestamp),(current_timestamp)") List nowWithLocalDateTimeList(); + // DATAJDBC-182 @Modifying @Query("UPDATE DUMMYENTITY SET name = :name WHERE id = :id") int updateName(@Param("id") Long id, @Param("name") String name); + // DATAJDBC-182 @Modifying @Query("DELETE FROM DUMMYENTITY WHERE name = :name") boolean deleteByName(@Param("name") String name); + // DATAJDBC-182 @Modifying @Query("INSERT INTO DUMMYENTITY (name) VALUES(:name)") void insert(@Param("name") String name);