Added checking so that missing columns give a clear message of the problem instead of quietly passing on nulls
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.neo4j.conversion;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.ResultColumn;
|
||||
import org.springframework.data.neo4j.support.conversion.NoSuchColumnFoundException;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
@@ -42,7 +43,14 @@ public class QueryMapResulConverter<T> implements ResultConverter<Map<String, Ob
|
||||
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
|
||||
ResultColumn column = method.getAnnotation(ResultColumn.class);
|
||||
TypeInformation<Object> returnType = ClassTypeInformation.fromReturnTypeOf(method);
|
||||
Object columnValue = valueCopy.get(column.value());
|
||||
|
||||
String columnName = column.value();
|
||||
if(!valueCopy.containsKey( columnName )) {
|
||||
throw new NoSuchColumnFoundException( columnName );
|
||||
}
|
||||
|
||||
Object columnValue = valueCopy.get( columnName );
|
||||
|
||||
|
||||
Object result;
|
||||
if (returnType.isCollectionLike())
|
||||
|
||||
@@ -99,7 +99,13 @@ public class EntityResultConverter<T, R> extends DefaultConverter<T, R> {
|
||||
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
|
||||
ResultColumn column = method.getAnnotation(ResultColumn.class);
|
||||
TypeInformation<?> returnType = ClassTypeInformation.fromReturnTypeOf(method);
|
||||
Object columnValue = map.get(column.value());
|
||||
|
||||
String columnName = column.value();
|
||||
if(!map.containsKey( columnName )) {
|
||||
throw new NoSuchColumnFoundException( columnName );
|
||||
}
|
||||
|
||||
Object columnValue = map.get( columnName );
|
||||
if(columnValue==null) return null;
|
||||
|
||||
// If the returned value is a Scala iterable, transform it to a Java iterable first
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright 2011 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
|
||||
*
|
||||
* http://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.neo4j.support.conversion;
|
||||
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
|
||||
public class NoSuchColumnFoundException extends MappingException {
|
||||
public NoSuchColumnFoundException( String column ) {
|
||||
super( "Expexted a column named "+ column + " to be in the result set." );
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import org.springframework.data.neo4j.annotation.ResultColumn;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jPersistentTestBase;
|
||||
import org.springframework.data.neo4j.model.Friendship;
|
||||
import org.springframework.data.neo4j.model.Person;
|
||||
import org.springframework.data.neo4j.support.conversion.NoSuchColumnFoundException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -40,67 +41,76 @@ public class QueryMapResultConverterTest extends Neo4jPersistentTestBase {
|
||||
private Map<String, Object> advancedMap;
|
||||
|
||||
public interface PersonAndFriendsData {
|
||||
@ResultColumn("person")
|
||||
@ResultColumn( "person" )
|
||||
Person getPerson();
|
||||
|
||||
@ResultColumn("collect(r)")
|
||||
@ResultColumn( "collect(r)" )
|
||||
Iterable<Friendship> getFriends();
|
||||
}
|
||||
|
||||
public interface SimplestQuery {
|
||||
@ResultColumn("name")
|
||||
@ResultColumn( "name" )
|
||||
String getName();
|
||||
|
||||
@ResultColumn("age")
|
||||
@ResultColumn( "age" )
|
||||
Integer getAge();
|
||||
|
||||
@ResultColumn("friends")
|
||||
@ResultColumn( "friends" )
|
||||
Iterable<String> getFriendNames();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
storeInGraph(michael);
|
||||
storeInGraph(andres);
|
||||
storeInGraph(emil);
|
||||
storeInGraph( michael );
|
||||
storeInGraph( andres );
|
||||
storeInGraph( emil );
|
||||
|
||||
makeFriends(michaelNode(), andresNode(), 19);
|
||||
makeFriends(michaelNode(), emilNode(), 6);
|
||||
makeFriends( michaelNode(), andresNode(), 19 );
|
||||
makeFriends( michaelNode(), emilNode(), 6 );
|
||||
|
||||
friends = asList("Michael", "Emil", "Anders");
|
||||
simpleMap = map("name", "Andres", "age", 36L, "friends", friends);
|
||||
advancedMap = map("person", michaelNode(), "collect(r)", michaelNode().getRelationships(KNOWS));
|
||||
friends = asList( "Michael", "Emil", "Anders" );
|
||||
simpleMap = map( "name", "Andres", "age", 36L, "friends", friends );
|
||||
advancedMap = map( "person", michaelNode(), "collect(r)", michaelNode().getRelationships( KNOWS ) );
|
||||
|
||||
michael = readPerson(michaelNode());
|
||||
michael = readPerson( michaelNode() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeAbleToGetAStringFromAResultMap() throws Exception {
|
||||
QueryMapResulConverter<SimplestQuery> converter = getConverter();
|
||||
SimplestQuery query = converter.convert(simpleMap, SimplestQuery.class);
|
||||
SimplestQuery query = converter.convert( simpleMap, SimplestQuery.class );
|
||||
|
||||
assertThat(query.getName(), equalTo("Andres"));
|
||||
assertThat(query.getAge(), equalTo(36));
|
||||
assertThat( query.getName(), equalTo( "Andres" ) );
|
||||
assertThat( query.getAge(), equalTo( 36 ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeAbleToHandleAnIterableOfString() throws Exception {
|
||||
QueryMapResulConverter<SimplestQuery> converter = getConverter();
|
||||
SimplestQuery query = converter.convert(simpleMap, SimplestQuery.class);
|
||||
SimplestQuery query = converter.convert( simpleMap, SimplestQuery.class );
|
||||
|
||||
assertThat(query.getFriendNames(), hasItems("Michael", "Emil", "Anders"));
|
||||
assertThat( query.getFriendNames(), hasItems( "Michael", "Emil", "Anders" ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHandleANodeBackedEntity() throws Exception {
|
||||
QueryMapResulConverter<PersonAndFriendsData> converter = new QueryMapResulConverter<PersonAndFriendsData>(template);
|
||||
PersonAndFriendsData result = converter.convert(advancedMap, PersonAndFriendsData.class);
|
||||
QueryMapResulConverter<PersonAndFriendsData> converter = new QueryMapResulConverter<PersonAndFriendsData>(
|
||||
template );
|
||||
PersonAndFriendsData result = converter.convert( advancedMap, PersonAndFriendsData.class );
|
||||
|
||||
assertThat(result.getPerson(), equalTo(michael));
|
||||
assertThat(asCollection(result.getFriends()), equalTo(asCollection(michael.getFriendships())));
|
||||
assertThat( result.getPerson(), equalTo( michael ) );
|
||||
assertThat( asCollection( result.getFriends() ), equalTo( asCollection( michael.getFriendships() ) ) );
|
||||
}
|
||||
|
||||
@Test( expected = NoSuchColumnFoundException.class )
|
||||
public void shouldThrowNiceException() throws Exception {
|
||||
QueryMapResulConverter<PersonAndFriendsData> converter = new QueryMapResulConverter<PersonAndFriendsData>(
|
||||
template );
|
||||
PersonAndFriendsData convert = converter.convert( map(), PersonAndFriendsData.class );
|
||||
convert.getFriends();
|
||||
}
|
||||
|
||||
private QueryMapResulConverter<SimplestQuery> getConverter() {
|
||||
return new QueryMapResulConverter<SimplestQuery>(template);
|
||||
return new QueryMapResulConverter<SimplestQuery>( template );
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.neo4j.model.Group;
|
||||
import org.springframework.data.neo4j.model.Person;
|
||||
import org.springframework.data.neo4j.support.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.support.conversion.NoSuchColumnFoundException;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -45,6 +46,7 @@ import static java.util.Arrays.asList;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
|
||||
import static org.junit.internal.matchers.IsCollectionContaining.hasItems;
|
||||
import static org.neo4j.helpers.collection.IteratorUtil.addToCollection;
|
||||
@@ -79,13 +81,13 @@ public class GraphRepositoryTest {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
testTeam = new TestTeam();
|
||||
testTeam.createSDGTeam(personRepository, groupRepository, friendshipRepository);
|
||||
testTeam.createSDGTeam( personRepository, groupRepository, friendshipRepository );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindIterableOfPersonWithQueryAnnotation() {
|
||||
Iterable<Person> teamMembers = personRepository.findAllTeamMembers(testTeam.sdg);
|
||||
assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david, testTeam.emil));
|
||||
assertThat( asCollection( teamMembers ), hasItems( testTeam.michael, testTeam.david, testTeam.emil ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -93,23 +95,23 @@ public class GraphRepositoryTest {
|
||||
Iterable<Person> teamMembers = personRepository.findWithinBoundingBox("personLayer", 55, 15, 57, 17);
|
||||
assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFindIterableOfPersonWithQueryAnnotationAndGremlin() {
|
||||
Iterable<Person> teamMembers = personRepository.findAllTeamMembersGremlin(testTeam.sdg);
|
||||
assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david, testTeam.emil));
|
||||
Iterable<Person> teamMembers = personRepository.findAllTeamMembersGremlin( testTeam.sdg );
|
||||
assertThat( asCollection( teamMembers ), hasItems( testTeam.michael, testTeam.david, testTeam.emil ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindPersonWithQueryAnnotation() {
|
||||
Person boss = personRepository.findBoss(testTeam.michael);
|
||||
assertThat(boss, is(testTeam.emil));
|
||||
Person boss = personRepository.findBoss( testTeam.michael );
|
||||
assertThat(boss, is( testTeam.emil ));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindPersonWithQueryAnnotationUsingLongAsParameter() {
|
||||
Person boss = personRepository.findBoss(testTeam.michael.getId());
|
||||
assertThat(boss, is(testTeam.emil));
|
||||
Person boss = personRepository.findBoss( testTeam.michael.getId() );
|
||||
assertThat(boss, is( testTeam.emil ));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -173,4 +175,10 @@ public class GraphRepositoryTest {
|
||||
Iterable<Person> findByName = personRepository.findByName(testTeam.michael.getName());
|
||||
assertThat(findByName, hasItem(testTeam.michael));
|
||||
}
|
||||
|
||||
@Test( expected = NoSuchColumnFoundException.class)
|
||||
public void missingColumnIsReportedNicely() {
|
||||
Iterable<MemberData> findByName = personRepository.nonWorkingQuery( testTeam.michael );
|
||||
Person boss = findByName.iterator().next().getBoss();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,10 @@ public interface PersonRepository extends GraphRepository<Person>, NamedIndexRep
|
||||
@Query("start member=node({p_person}) match team-[:persons]->member<-[?:boss]-boss return collect(team), boss")
|
||||
Iterable<MemberData> findMemberData(@Param("p_person") Person person);
|
||||
|
||||
@Query("start member=node({p_person}) match team-[:persons]->member<-[?:boss]-boss return member")
|
||||
Iterable<MemberData> nonWorkingQuery(@Param("p_person") Person person);
|
||||
|
||||
|
||||
@Query("start person=node({p_person}) match (boss)-[:boss]->(person) return boss")
|
||||
Person findBoss(@Param("p_person") Person person);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user