Added checking so that missing columns give a clear message of the problem instead of quietly passing on nulls

This commit is contained in:
Andres Taylor
2011-11-01 08:22:26 +01:00
parent 269a2e14a3
commit a6f3a9a7c7
6 changed files with 95 additions and 35 deletions

View File

@@ -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())

View File

@@ -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

View File

@@ -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." );
}
}

View File

@@ -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 );
}
}

View File

@@ -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();
}
}

View File

@@ -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);