DATAJDBC-175 - Supports simple types as return type for annotated methods.

Original pull request: #43.
This commit is contained in:
Kazuki Shimizu
2018-02-09 21:15:47 +09:00
committed by Jens Schauder
parent 4cb50caf79
commit 369ca6d599
3 changed files with 75 additions and 4 deletions

View File

@@ -44,6 +44,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
*
* @author Jens Schauder
* @author Greg Turnquist
* @author Kazuki Shimizu
* @since 2.0
*/
public class JdbcMappingContext extends AbstractMappingContext<JdbcPersistentEntity<?>, JdbcPersistentProperty> {
@@ -56,6 +57,7 @@ public class JdbcMappingContext extends AbstractMappingContext<JdbcPersistentEnt
@Getter private final NamingStrategy namingStrategy;
@Getter private final NamedParameterJdbcOperations template;
@Getter private SimpleTypeHolder simpleTypeHolder;
private GenericConversionService conversions = getDefaultConversionService();
public JdbcMappingContext(NamingStrategy namingStrategy, NamedParameterJdbcOperations template,
@@ -72,6 +74,12 @@ public class JdbcMappingContext extends AbstractMappingContext<JdbcPersistentEnt
this(new DefaultNamingStrategy(), template, __ -> {});
}
@Override
public void setSimpleTypeHolder(SimpleTypeHolder simpleTypes) {
super.setSimpleTypeHolder(simpleTypes);
this.simpleTypeHolder = simpleTypes;
}
public List<PropertyPath> referencedEntities(Class<?> rootType, PropertyPath path) {
List<PropertyPath> paths = new ArrayList<>();

View File

@@ -17,6 +17,7 @@ package org.springframework.data.jdbc.repository.support;
import java.lang.reflect.Method;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.jdbc.core.DataAccessStrategy;
import org.springframework.data.jdbc.core.EntityRowMapper;
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
@@ -27,22 +28,26 @@ import org.springframework.data.repository.query.EvaluationContextProvider;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SingleColumnRowMapper;
/**
* {@link QueryLookupStrategy} for JDBC repositories. Currently only supports annotated queries.
*
* @author Jens Schauder
* @author Kazuki Shimizu
*/
class JdbcQueryLookupStrategy implements QueryLookupStrategy {
private final JdbcMappingContext context;
private final DataAccessStrategy accessStrategy;
private final ConversionService conversionService;
JdbcQueryLookupStrategy(EvaluationContextProvider evaluationContextProvider, JdbcMappingContext context,
DataAccessStrategy accessStrategy) {
this.context = context;
this.accessStrategy = accessStrategy;
this.conversionService = context.getConversions();
}
@Override
@@ -50,10 +55,12 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy {
ProjectionFactory projectionFactory, NamedQueries namedQueries) {
JdbcQueryMethod queryMethod = new JdbcQueryMethod(method, repositoryMetadata, projectionFactory);
Class<?> domainType = queryMethod.getReturnedObjectType();
RowMapper<?> rowMapper = new EntityRowMapper<>(context.getRequiredPersistentEntity(domainType),
context.getConversions(), context, accessStrategy);
Class<?> returnedObjectType = queryMethod.getReturnedObjectType();
RowMapper<?> rowMapper = context.getSimpleTypeHolder().isSimpleType(returnedObjectType)
? SingleColumnRowMapper.newInstance(returnedObjectType, conversionService)
: new EntityRowMapper<>(context.getRequiredPersistentEntity(returnedObjectType), conversionService,
context, accessStrategy);
return new JdbcRepositoryQuery(queryMethod, context, rowMapper);
}
}

View File

@@ -33,6 +33,8 @@ 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;
@@ -165,6 +167,48 @@ public class QueryAnnotationHsqlIntegrationTests {
.containsExactlyInAnyOrder("a", "b");
}
@Test // DATAJDBC-175
public void executeCustomQueryWithReturnTypeIsNubmer() {
repository.save(dummyEntity("aaa"));
repository.save(dummyEntity("bbb"));
repository.save(dummyEntity("cac"));
int count = repository.countByNameContaining("a");
assertThat(count).isEqualTo(2);
}
@Test // DATAJDBC-175
public void executeCustomQueryWithReturnTypeIsBoolean() {
repository.save(dummyEntity("aaa"));
repository.save(dummyEntity("bbb"));
repository.save(dummyEntity("cac"));
assertThat(repository.existsByNameContaining("a")).isTrue();
assertThat(repository.existsByNameContaining("d")).isFalse();
}
@Test // DATAJDBC-175
public void executeCustomQueryWithReturnTypeIsDate() {
Date now = new Date();
assertThat(repository.nowWithDate()).isAfterOrEqualsTo(now);
}
@Test // DATAJDBC-175
public void executeCustomQueryWithReturnTypeIsLocalDateTimeList() {
LocalDateTime now = LocalDateTime.now();
repository.nowWithLocalDateTimeList() //
.forEach(d -> assertThat(d).isAfterOrEqualTo(now));
}
private DummyEntity dummyEntity(String name) {
@@ -209,5 +253,17 @@ public class QueryAnnotationHsqlIntegrationTests {
@Query("SELECT * FROM DUMMYENTITY")
Stream<DummyEntity> findAllWithReturnTypeIsStream();
@Query("SELECT count(*) FROM DUMMYENTITY WHERE name like '%' || :name || '%'")
int countByNameContaining(@Param("name") String name);
@Query("SELECT count(*) FROM DUMMYENTITY WHERE name like '%' || :name || '%'")
boolean existsByNameContaining(@Param("name") String name);
@Query("VALUES (current_timestamp)")
Date nowWithDate();
@Query("VALUES (current_timestamp),(current_timestamp)")
List<LocalDateTime> nowWithLocalDateTimeList();
}
}