Read correct domain type when returning interface type from domain type hierarchy.

We now read the correct type to read (domain type) when a repository query method declares an interface type that is implemented by the domain type.

Closes #1335
This commit is contained in:
Mark Paluch
2023-01-03 15:17:47 +01:00
parent 745ae59c6f
commit 515bffc784
4 changed files with 92 additions and 12 deletions

View File

@@ -107,7 +107,7 @@ public abstract class AbstractCassandraQuery extends CassandraRepositoryQuerySup
CassandraReturnedType returnedType = new CassandraReturnedType(resultProcessor.getReturnedType(),
getOperations().getConverter().getCustomConversions());
return returnedType.isProjecting() ? returnedType.getDomainType() : returnedType.getReturnedType();
return returnedType.getResultType();
}
/**

View File

@@ -103,7 +103,7 @@ public abstract class AbstractReactiveCassandraQuery extends CassandraRepository
CassandraReturnedType returnedType = new CassandraReturnedType(resultProcessor.getReturnedType(),
getRequiredConverter(getReactiveCassandraOperations()).getCustomConversions());
return (returnedType.isProjecting() ? returnedType.getDomainType() : returnedType.getReturnedType());
return returnedType.getResultType();
}
/**

View File

@@ -19,7 +19,6 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
@@ -104,7 +103,22 @@ public abstract class CassandraRepositoryQuerySupport implements RepositoryQuery
this.customConversions = customConversions;
}
boolean isProjecting() {
public Class<?> getResultType() {
if (isProjecting()) {
return returnedType.getDomainType();
}
Class<?> typeToRead = returnedType.getTypeToRead();
if (typeToRead == null) {
return returnedType.getReturnedType();
}
return typeToRead;
}
private boolean isProjecting() {
if (!this.returnedType.isProjecting()) {
return false;
@@ -124,13 +138,5 @@ public abstract class CassandraRepositoryQuerySupport implements RepositoryQuery
// Don't apply projection on Cassandra simple types
return !this.customConversions.isSimpleType(this.returnedType.getReturnedType());
}
Class<?> getDomainType() {
return this.returnedType.getDomainType();
}
Class<?> getReturnedType() {
return this.returnedType.getReturnedType();
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.repository.query;
import static org.mockito.Mockito.*;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
/**
* Unit tests for {@link AbstractCassandraQuery}.
*
* @author Mark Paluch
*/
public class AbstractCassandraQueryUnitTests {
CassandraMappingContext context = new CassandraMappingContext();
CassandraOperations operations = mock(CassandraOperations.class);
@BeforeEach
void setUp() {
when(operations.getConverter()).thenReturn(new MappingCassandraConverter(context));
}
@Test
void shouldResolveDomainTypeForReturnedInterfaceInHierarchy() throws Exception {
DefaultRepositoryMetadata metadata = new DefaultRepositoryMetadata(MyRepository.class);
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
CassandraQueryMethod method = new CassandraQueryMethod(MyRepository.class.getMethod("findBy"), metadata, factory,
context);
PartTreeCassandraQuery cq = new PartTreeCassandraQuery(method, operations);
cq.execute(new Object[0]);
verify(operations).select(any(com.datastax.oss.driver.api.core.cql.Statement.class), eq(MyClass.class));
}
interface MyInterface {
}
static class MyClass implements MyInterface {
}
interface MyRepository extends CassandraRepository<MyClass, String> {
Optional<MyInterface> findBy();
}
}