DATAGRAPH-453

Neo4jOperations' "lookup" method throws IllegalStateException

lookup will now throw a more descriptive exception
added `findByIndexedValue()` method to Neo4jOperations for label based operations
This commit is contained in:
Michael Hunger
2014-03-31 04:28:05 +02:00
parent 4bcf040527
commit 928fca11e7
25 changed files with 141 additions and 374 deletions

View File

@@ -25,7 +25,6 @@ import org.neo4j.graphdb.schema.IndexDefinition;
import org.neo4j.helpers.collection.IteratorUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.aspects.core.NodeBacked;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.core.NodeTypeRepresentationStrategy;
import org.springframework.data.neo4j.support.Neo4jTemplate;
@@ -160,7 +159,7 @@ public abstract class SchemaIndexingEntityTestBase {
"return DISTINCT ID(n)", params);
assertNotNull(result);
EndResult<Long> results = result.to(Long.class);
Result<Long> results = result.to(Long.class);
return IteratorUtil.asCollection(results.iterator());
}

View File

@@ -1,75 +0,0 @@
/**
* 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.rest;
import org.neo4j.helpers.collection.IteratorUtil;
import org.neo4j.rest.graphdb.util.ConvertedResult;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.neo4j.conversion.ContainerConverter;
import org.springframework.data.neo4j.conversion.EndResult;
import java.util.Iterator;
class SpringEndResult<R> implements EndResult<R> {
private final ConvertedResult<R> result;
public SpringEndResult(ConvertedResult<R> result) {
this.result = result;
}
@Override
public R single() {
return result.single();
}
@Override
public R singleOrNull() {
return IteratorUtil.singleOrNull(result);
}
@Override
public void handle(final org.springframework.data.neo4j.conversion.Handler<R> rHandler) {
result.handle(new SpringHandler<R>(rHandler));
}
@Override
public Iterator<R> iterator() {
return result.iterator();
}
@Override
public <C extends Iterable<R>> C as(Class<C> container) {
return ContainerConverter.toContainer(container,this);
}
@Override
public Slice<R> slice(int page, int pageSize) {
return slice(new PageRequest(page,pageSize));
}
@Override
public Slice<R> slice(Pageable page) {
return ContainerConverter.slice(this, page);
}
@Override
public void finish()
{
}
}

View File

@@ -20,6 +20,8 @@ import org.neo4j.rest.graphdb.RestAPI;
import org.neo4j.rest.graphdb.query.RestCypherQueryEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.neo4j.conversion.QueryResultBuilder;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.conversion.ResultConverter;
import org.springframework.data.neo4j.support.query.CypherQueryEngine;
import org.springframework.data.neo4j.support.query.QueryEngine;
@@ -40,10 +42,10 @@ public class SpringRestCypherQueryEngine implements CypherQueryEngine {
}
@Override
public SpringRestResult<Map<String,Object>> query(String statement, Map<String, Object> params) {
public Result<Map<String,Object>> query(String statement, Map<String, Object> params) {
if (log.isDebugEnabled()) log.debug(String.format("Executing remote cypher query: %s params %s",statement,params));
return new SpringRestResult<Map<String, Object>>(restCypherQueryEngine.query(statement, params));
return new QueryResultBuilder<Map<String, Object>>(restCypherQueryEngine.query(statement, params), resultConverter);
}
public ResultConverter getResultConverter() {

View File

@@ -1,103 +0,0 @@
/**
* 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.rest;
import org.neo4j.rest.graphdb.util.ConvertedResult;
import org.neo4j.rest.graphdb.util.ResultConverter;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.neo4j.conversion.ContainerConverter;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.mapping.MappingPolicy;
import java.util.Iterator;
import static org.springframework.data.neo4j.conversion.ContainerConverter.toContainer;
class SpringRestResult<T> implements Result<T> {
org.neo4j.rest.graphdb.util.QueryResult<T> queryResult;
private MappingPolicy mappingPolicy;
SpringRestResult(org.neo4j.rest.graphdb.util.QueryResult<T> queryResult) {
this.queryResult = queryResult;
}
@Override
public <R> EndResult<R> to(final Class<R> type) {
return new SpringEndResult<R>(queryResult.to(type));
}
public <R> EndResult<R> to(Class<R> type, final org.springframework.data.neo4j.conversion.ResultConverter<T, R> converter) {
ConvertedResult<R> result = queryResult.to(type, new ResultConverter<T, R>() {
@Override
public R convert(T value, Class<R> type) {
return converter.convert(value,type,mappingPolicy);
}
});
return new SpringEndResult<R>(result);
}
public void handle(org.springframework.data.neo4j.conversion.Handler<T> handler) {
queryResult.handle(new SpringHandler<T>(handler));
}
@Override
public Slice<T> slice(int page, int pageSize) {
return slice(new PageRequest(page,pageSize));
}
@Override
public Slice<T> slice(Pageable page) {
return ContainerConverter.slice( queryResult, page );
}
@Override
public Iterator<T> iterator() {
return queryResult.iterator();
}
@SuppressWarnings({"unchecked"})
@Override
public T singleOrNull() {
return (T) to(Object.class).singleOrNull();
}
@SuppressWarnings("unchecked")
@Override
public T single() {
return (T) to(Object.class).single();
}
@Override
public Result<T> with(MappingPolicy mappingPolicy) {
this.mappingPolicy = mappingPolicy;
return this;
}
@Override
public <C extends Iterable<T>> C as(Class<C> container) {
return toContainer(container, this);
}
@Override
public void finish()
{
}
}

View File

@@ -1,34 +0,0 @@
/**
* 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.conversion;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
/**
* @author mh
* @since 28.06.11
*/
public interface EndResult<R> extends Iterable<R> {
R single();
R singleOrNull();
void handle(Handler<R> handler);
<C extends Iterable<R>> C as(Class<C> container);
Slice<R> slice(int page, int pageSize);
Slice<R> slice(Pageable page);
void finish();
}

View File

@@ -18,6 +18,7 @@ package org.springframework.data.neo4j.conversion;
import org.neo4j.graphdb.index.IndexHits;
import org.neo4j.helpers.collection.ClosableIterable;
import org.neo4j.helpers.collection.IterableWrapper;
import org.neo4j.helpers.collection.IteratorUtil;
import org.neo4j.helpers.collection.IteratorWrapper;
import org.springframework.data.domain.PageRequest;
@@ -46,13 +47,13 @@ public class QueryResultBuilder<T> implements Result<T> {
public QueryResultBuilder(Iterable<T> result, final ResultConverter<T,?> defaultConverter) {
this.result = result;
this.isClosableIterable = result instanceof IndexHits || result instanceof ClosableIterable;
this.isClosableIterable = result instanceof IndexHits || result instanceof ClosableIterable || result instanceof AutoCloseable;
this.defaultConverter = defaultConverter;
}
@SuppressWarnings("unchecked")
@Override
public <R> EndResult<R> to(Class<R> type) {
public <R> Result<R> to(Class<R> type) {
return this.to(type, defaultConverter);
}
@@ -80,75 +81,17 @@ public class QueryResultBuilder<T> implements Result<T> {
}
@Override
public <R> EndResult<R> to(final Class<R> type, final ResultConverter<T, R> resultConverter) {
return new EndResult<R>() {
public <R> Result<R> to(final Class<R> type, final ResultConverter<T, R> resultConverter) {
Iterable<R> it = new IterableWrapper<R, T>(result) {
@Override
public R single() {
try {
final T value = IteratorUtil.single(result);
return convert(value);
} finally {
closeIfNeeded();
}
}
@Override
public R singleOrNull() {
try {
final T value = IteratorUtil.singleOrNull(result);
if (value==null) return null;
return convert(value);
} finally {
closeIfNeeded();
}
}
private R convert(T value) {
return resultConverter.convert(value, type, mappingPolicy);
}
@Override
public void handle(Handler<R> handler) {
try {
for (T value : result) {
handler.handle(convert(value));
}
} finally {
closeIfNeeded();
}
}
@Override
public Iterator<R> iterator() {
return new IteratorWrapper<R, T>(result.iterator()) {
protected R underlyingObjectToObject(T value) {
return convert(value);
}
};
}
@Override
public <C extends Iterable<R>> C as(Class<C> container) {
return ContainerConverter.toContainer(container, this);
}
@Override
public Slice<R> slice(Pageable page) {
return ContainerConverter.slice(this,page);
}
@Override
public Slice<R> slice(int page, int size) {
return ContainerConverter.slice(this,new PageRequest(page,size));
}
@Override
public void finish()
{
closeIfNeeded();
protected R underlyingObjectToObject(T object) {
return resultConverter.convert(object,type,mappingPolicy);
}
};
return new QueryResultBuilder<R>(it,defaultConverter);
}
@SuppressWarnings("unchecked")
@Override
public <C extends Iterable<T>> C as(Class<C> container) {

View File

@@ -16,15 +16,28 @@
package org.springframework.data.neo4j.conversion;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.neo4j.mapping.MappingPolicy;
/**
* @author mh
* @since 28.06.11
*/
public interface Result<T> extends EndResult<T> {
<R> EndResult<R> to(Class<R> type);
<R> EndResult<R> to(Class<R> type, ResultConverter<T, R> resultConverter);
public interface Result<T> extends Iterable<T> {
<R> Result<R> to(Class<R> type);
<R> Result<R> to(Class<R> type, ResultConverter<T, R> resultConverter);
Result<T> with(MappingPolicy mappingPolicy);
T single();
T singleOrNull();
void handle(Handler<T> handler);
<C extends Iterable<T>> C as(Class<C> container);Slice<T> slice(int page, int pageSize);
Slice<T> slice(Pageable page);
void finish();
}

View File

@@ -27,7 +27,7 @@ import org.springframework.data.domain.*;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Shape;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.repository.query.CypherQuery;
@@ -112,7 +112,7 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
* @return lazy Iterable over all instances of the target type.
*/
@Override
public EndResult<T> findAll() {
public Result<T> findAll() {
return template.findAll(clazz);
}
@@ -166,7 +166,7 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
*/
@Override
@Deprecated
public EndResult<T> findAllByPropertyValue(final String indexName, final String property, final Object value) {
public Result<T> findAllByPropertyValue(final String indexName, final String property, final Object value) {
return legacyIndexSearcher.findAllByPropertyValue(indexName, property, value);
}
@@ -177,7 +177,7 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
* @return Iterable over Entities with this property and value
*/
@Override
public EndResult<T> findAllByPropertyValue(final String property, final Object value) {
public Result<T> findAllByPropertyValue(final String property, final Object value) {
return findAllByPropertyValue(null, property, value);
}
@@ -189,7 +189,7 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
*/
@Override
@Deprecated
public EndResult<T> findAllByQuery(final String key, final Object query) {
public Result<T> findAllByQuery(final String key, final Object query) {
return findAllByQuery(null, key,query);
}
/**
@@ -201,18 +201,18 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
*/
@Override
@Deprecated
public EndResult<T> findAllByQuery(final String indexName, final String property, final Object query) {
public Result<T> findAllByQuery(final String indexName, final String property, final Object query) {
return legacyIndexSearcher.findAllByQuery(indexName, property, query);
}
@Override
@Deprecated
public EndResult<T> findAllByRange(final String property, final Number from, final Number to) {
public Result<T> findAllByRange(final String property, final Number from, final Number to) {
return findAllByRange(null,property,from,to);
}
@Override
@Deprecated
public EndResult<T> findAllByRange(final String indexName, final String property, final Number from, final Number to) {
public Result<T> findAllByRange(final String indexName, final String property, final Number from, final Number to) {
return legacyIndexSearcher.findAllByRange(indexName, property, from, to);
}
@@ -238,7 +238,7 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
* @return Iterable over Entities with this property and value
*/
@Override
public EndResult<T> findAllBySchemaPropertyValue(String property, Object value) {
public Result<T> findAllBySchemaPropertyValue(String property, Object value) {
final String SCHEMA_PROP_MATCH_CLAUSE = "MATCH (entity:`%s`) where entity.`%s` = {propValue} return entity";
Neo4jPersistentEntity persistentEntity = template.getEntityType(clazz).getEntity();
@@ -297,13 +297,13 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
}
@Override
public EndResult<T> findAll(Sort sort) {
public Result<T> findAll(Sort sort) {
CypherQuery cq = new CypherQuery(template.getEntityType(clazz).getEntity(),template, template.isLabelBased());
return query(cq.toQueryString(sort), Collections.EMPTY_MAP);
}
@Override
public EndResult<T> query(String query, Map<String, Object> params) {
public Result<T> query(String query, Map<String, Object> params) {
return template.query(query, params).to(clazz);
}
@@ -311,7 +311,7 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
public Page<T> findAll(final Pageable pageable) {
int count = pageable.getPageSize();
int offset = pageable.getOffset();
EndResult<T> foundEntities = findAll(pageable.getSort());
Result<T> foundEntities = findAll(pageable.getSort());
final Iterator<T> iterator = foundEntities.iterator();
final PageImpl<T> page = extractPage(pageable, count, offset, iterator);
foundEntities.finish();
@@ -396,39 +396,39 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
@SuppressWarnings("unchecked")
@Override
public EndResult<T> query(Execute query, Map<String, Object> params) {
public Result<T> query(Execute query, Map<String, Object> params) {
return template.queryEngineFor().query(query.toString(), params).to(clazz);
}
// SpatialRepository
@Override
public EndResult<T> findWithinWellKnownText( final String indexName, String wellKnownText) {
public Result<T> findWithinWellKnownText(final String indexName, String wellKnownText) {
return geoQueries.findWithinWellKnownText(indexName,wellKnownText);
}
@Override
public EndResult<T> findWithinDistance( final String indexName, final double lat, double lon, double distanceKm) {
public Result<T> findWithinDistance(final String indexName, final double lat, double lon, double distanceKm) {
return geoQueries.findWithinDistance(indexName, lat, lon,distanceKm);
}
@Override
public EndResult<T> findWithinBoundingBox(final String indexName, final double lowerLeftLat,
final double lowerLeftLon, final double upperRightLat, final double upperRightLon) {
public Result<T> findWithinBoundingBox(final String indexName, final double lowerLeftLat,
final double lowerLeftLon, final double upperRightLat, final double upperRightLon) {
return geoQueries.findWithinBoundingBox(indexName, lowerLeftLat, lowerLeftLon, upperRightLat, upperRightLon);
}
@Override
public EndResult<T> findWithinBoundingBox(String indexName, Box box) {
public Result<T> findWithinBoundingBox(String indexName, Box box) {
return geoQueries.findWithinBoundingBox(indexName,box);
}
@Override
public EndResult<T> findWithinDistance(String indexName, Circle circle) {
public Result<T> findWithinDistance(String indexName, Circle circle) {
return geoQueries.findWithinDistance(indexName, circle);
}
@Override
public EndResult<T> findWithinShape(String indexName, Shape shape) {
public Result<T> findWithinShape(String indexName, Shape shape) {
return geoQueries.findWithinShape(indexName,shape);
}
}

View File

@@ -19,7 +19,7 @@ package org.springframework.data.neo4j.repository;
import java.util.Map;
import org.springframework.data.domain.Sort;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
@@ -38,7 +38,7 @@ public interface CRUDRepository<T> extends PagingAndSortingRepository<T, Long> {
* @return all entities of the given type
* NOTE: please close the iterable if it is not fully looped through
*/
EndResult<T> findAll();
Result<T> findAll();
/**
@@ -48,11 +48,11 @@ public interface CRUDRepository<T> extends PagingAndSortingRepository<T, Long> {
* @return all elements of the repository type, sorted according to the sort
* NOTE: please close the iterable if it is not fully looped through
*/
EndResult<T> findAll(Sort sort);
Result<T> findAll(Sort sort);
Class getStoredJavaType(Object entity);
EndResult<T> query(String query, Map<String, Object> params);
}
Result<T> query(String query, Map<String, Object> params);
}

View File

@@ -18,7 +18,7 @@ package org.springframework.data.neo4j.repository;
import org.neo4j.cypherdsl.grammar.Execute;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@@ -33,5 +33,5 @@ public interface CypherDslRepository<T> {
@Transactional
Page<T> query(Execute query, Execute countQuery, Map<String, Object> params, Pageable page);
@Transactional
EndResult<T> query(Execute query, Map<String, Object> params);
Result<T> query(Execute query, Map<String, Object> params);
}

View File

@@ -21,7 +21,7 @@ import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.helpers.Pair;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.geo.*;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.repository.query.parser.Part;
import org.springframework.util.Assert;
@@ -40,12 +40,12 @@ public class GeoQueries<S extends PropertyContainer, T> implements SpatialReposi
this.legacyIndexSearcher = legacyIndexSearcher;
}
@Override
public EndResult<T> findWithinWellKnownText( final String indexName, String wellKnownText) {
public Result<T> findWithinWellKnownText(final String indexName, String wellKnownText) {
return legacyIndexSearcher.geoQuery(indexName, WITHIN_WKT_GEOMETRY, wellKnownText);
}
@Override
public EndResult<T> findWithinShape(String indexName, Shape shape) {
public Result<T> findWithinShape(String indexName, Shape shape) {
Assert.notNull(indexName, "geo-index-name must not be null");
Assert.notNull(shape,"shape must not be null");
if (shape instanceof Circle) return findWithinDistance(indexName,(Circle)shape);
@@ -55,7 +55,7 @@ public class GeoQueries<S extends PropertyContainer, T> implements SpatialReposi
}
@Override
public EndResult<T> findWithinDistance( final String indexName, final double lat, double lon, double distanceKm) {
public Result<T> findWithinDistance(final String indexName, final double lat, double lon, double distanceKm) {
return legacyIndexSearcher.geoQuery(indexName, WITHIN_DISTANCE, toWithinDistanceParams(lat, lon, distanceKm));
}
@@ -64,7 +64,7 @@ public class GeoQueries<S extends PropertyContainer, T> implements SpatialReposi
}
@Override
public EndResult<T> findWithinDistance(String indexName, Circle circle) {
public Result<T> findWithinDistance(String indexName, Circle circle) {
return legacyIndexSearcher.geoQuery(indexName, WITHIN_DISTANCE, toWithinDistanceParams(circle));
}
@@ -78,8 +78,8 @@ public class GeoQueries<S extends PropertyContainer, T> implements SpatialReposi
}
@Override
public EndResult<T> findWithinBoundingBox(final String indexName, final double lowerLeftLat,
final double lowerLeftLon, final double upperRightLat, final double upperRightLon) {
public Result<T> findWithinBoundingBox(final String indexName, final double lowerLeftLat,
final double lowerLeftLon, final double upperRightLat, final double upperRightLon) {
return legacyIndexSearcher.geoQuery(indexName, BBOX, toBoundingBoxParams(lowerLeftLat, lowerLeftLon, upperRightLat, upperRightLon));
}
@@ -88,7 +88,7 @@ public class GeoQueries<S extends PropertyContainer, T> implements SpatialReposi
}
@Override
public EndResult<T> findWithinBoundingBox(String indexName, Box box) {
public Result<T> findWithinBoundingBox(String indexName, Box box) {
return legacyIndexSearcher.geoQuery(indexName,BBOX,toBoundingBoxParams(box));
}

View File

@@ -16,7 +16,7 @@
package org.springframework.data.neo4j.repository;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.transaction.annotation.Transactional;
@@ -29,12 +29,12 @@ import org.springframework.transaction.annotation.Transactional;
T findByPropertyValue(String property, Object value);
@Transactional @Deprecated
EndResult<T> findAllByPropertyValue(String property, Object value);
Result<T> findAllByPropertyValue(String property, Object value);
@Transactional @Deprecated
EndResult<T> findAllByQuery(String key, Object query);
Result<T> findAllByQuery(String key, Object query);
@Transactional @Deprecated
EndResult<T> findAllByRange(String property, Number from, Number to);
Result<T> findAllByRange(String property, Number from, Number to);
}

View File

@@ -7,7 +7,6 @@ import org.neo4j.graphdb.index.IndexHits;
import org.neo4j.graphdb.index.ReadableIndex;
import org.neo4j.helpers.collection.ClosableIterable;
import org.neo4j.helpers.collection.IterableWrapper;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.Neo4jTemplate;
@@ -100,7 +99,7 @@ public class LegacyIndexSearcher<S extends PropertyContainer,T> {
return (NumericRangeQuery<T>) NumericRangeQuery.newIntRange(property, from.intValue(), to.intValue(), true, true);
}
public EndResult<T> findAllByRange(String indexName, final String property, final Number from, final Number to) {
public Result<T> findAllByRange(String indexName, final String property, final Number from, final Number to) {
return queryResult(indexName, new AbstractGraphRepository.Query<S>() {
public IndexHits<S> query(ReadableIndex<S> index) {
return index.query(property, createInclusiveRangeQuery(property, from, to));
@@ -108,7 +107,7 @@ public class LegacyIndexSearcher<S extends PropertyContainer,T> {
});
}
public EndResult<T> findAllByQuery(final String indexName, final String property, final Object query) {
public Result<T> findAllByQuery(final String indexName, final String property, final Object query) {
return queryResult(indexName, new AbstractGraphRepository.Query<S>() {
public IndexHits<S> query(ReadableIndex<S> index) {
return getIndex(indexName, property).query(property, query);
@@ -127,7 +126,7 @@ public class LegacyIndexSearcher<S extends PropertyContainer,T> {
}
public EndResult<T> findAllByPropertyValue(final String indexName, final String property, final Object value) {
public Result<T> findAllByPropertyValue(final String indexName, final String property, final Object value) {
return queryResult(indexName, new AbstractGraphRepository.Query<S>() {
public IndexHits<S> query(ReadableIndex<S> index) {
return getIndexHits(indexName, property, value);
@@ -135,7 +134,7 @@ public class LegacyIndexSearcher<S extends PropertyContainer,T> {
});
}
private EndResult<T> queryResult(String indexName, AbstractGraphRepository.Query<S> query) {
private Result<T> queryResult(String indexName, AbstractGraphRepository.Query<S> query) {
try {
final IndexHits<S> indexHits = query.query(getIndex(indexName, null));
return template.convert(indexHits).to(clazz);

View File

@@ -16,7 +16,7 @@
package org.springframework.data.neo4j.repository;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.transaction.annotation.Transactional;
@@ -29,12 +29,12 @@ import org.springframework.transaction.annotation.Transactional;
T findByPropertyValue(String indexName, String property, Object value);
@Transactional @Deprecated
EndResult<T> findAllByPropertyValue(String indexName, String property, Object value);
Result<T> findAllByPropertyValue(String indexName, String property, Object value);
@Transactional @Deprecated
EndResult<T> findAllByQuery(String indexName, String key, Object query);
Result<T> findAllByQuery(String indexName, String key, Object query);
@Transactional @Deprecated
EndResult<T> findAllByRange(String indexName, String property, Number from, Number to);
Result<T> findAllByRange(String indexName, String property, Number from, Number to);
}

View File

@@ -16,7 +16,7 @@
package org.springframework.data.neo4j.repository;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.transaction.annotation.Transactional;
@@ -30,6 +30,6 @@ public interface SchemaIndexRepository<T> {
T findBySchemaPropertyValue(String property, Object value);
@Transactional
EndResult<T> findAllBySchemaPropertyValue(String property, Object value);
Result<T> findAllBySchemaPropertyValue(String property, Object value);
}

View File

@@ -18,11 +18,9 @@ package org.springframework.data.neo4j.repository;
import org.springframework.data.geo.*;
import org.springframework.data.geo.Shape;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.transaction.annotation.Transactional;
import java.awt.*;
/**
* Repository for spatial queries.
*
@@ -35,27 +33,27 @@ import java.awt.*;
*/
public interface SpatialRepository<T> {
@Transactional
EndResult<T> findWithinBoundingBox(String indexName, double lowerLeftLat,
double lowerLeftLon,
double upperRightLat,
double upperRightLon);
Result<T> findWithinBoundingBox(String indexName, double lowerLeftLat,
double lowerLeftLon,
double upperRightLat,
double upperRightLon);
@Transactional
EndResult<T> findWithinBoundingBox(String indexName, Box box);
Result<T> findWithinBoundingBox(String indexName, Box box);
@Transactional
EndResult<T> findWithinDistance( final String indexName, final double lat, double lon, double distanceKm);
Result<T> findWithinDistance(final String indexName, final double lat, double lon, double distanceKm);
@Transactional
EndResult<T> findWithinDistance( final String indexName, Circle circle);
Result<T> findWithinDistance(final String indexName, Circle circle);
@Transactional
EndResult<T> findWithinWellKnownText( final String indexName, String wellKnownText);
Result<T> findWithinWellKnownText(final String indexName, String wellKnownText);
/**
* Converts the shape into a well-known text representation and executes the appropriate WKT query
*/
@Transactional
EndResult<T> findWithinShape( final String indexName, Shape shape);
Result<T> findWithinShape(final String indexName, Shape shape);
}

View File

@@ -21,7 +21,7 @@ import org.neo4j.helpers.collection.IteratorUtil;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.SliceImpl;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.core.GraphDatabase;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.query.CypherQueryEngine;
@@ -109,7 +109,7 @@ abstract class GraphRepositoryQuery implements RepositoryQuery, ParameterResolve
return createPage(result, accessor.getPageable(),count, queryMethod.isPageQuery());
}
if (queryMethod.isIterableResult()) {
final EndResult<?> result = queryEngine.query(queryString, params).to(compoundType);
final Result<?> result = queryEngine.query(queryString, params).to(compoundType);
if (queryMethod.isSetResult()) return IteratorUtil.addToCollection(result,new LinkedHashSet());
if (queryMethod.isCollectionResult()) return IteratorUtil.addToCollection(result,new ArrayList());
return result;

View File

@@ -30,7 +30,6 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.QueryResultBuilder;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.conversion.ResultConverter;
@@ -202,7 +201,7 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationContextAware {
}
@Override
public <T> EndResult<T> findAll(final Class<T> entityClass) {
public <T> Result<T> findAll(final Class<T> entityClass) {
notNull(entityClass, "entity type");
final ClosableIterable<PropertyContainer> all = infrastructure.getTypeRepresentationStrategies().findAll(getEntityType(entityClass));
return new QueryResultBuilder<PropertyContainer>(all, getDefaultConverter()).to(entityClass);
@@ -369,7 +368,7 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationContextAware {
final Class<Object> targetType = (Class<Object>) actualType.getType();
final Result<Map<String, Object>> result = queryEngineFor().query(statement, params);
final Class<? extends Iterable<Object>> containerType = (Class<? extends Iterable<Object>>) typeInformation.getType();
if (EndResult.class.isAssignableFrom(containerType)) {
if (Result.class.isAssignableFrom(containerType)) {
return result;
}
if (actualType.isMap()) {
@@ -613,7 +612,6 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationContextAware {
public <T extends PropertyContainer> Result<T> lookup(final Class<?> indexedType, String propertyName, final Object value) {
notNull(propertyName, "property name", indexedType, "indexedType", value, "query value");
try {
final Index<T> index = getIndex(indexedType, propertyName);
return convert(index.query(propertyName, value));
} catch (RuntimeException e) {
@@ -621,6 +619,13 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationContextAware {
}
}
@Override
public <T> Result<T> findByIndexedValue(final Class<? extends T> indexedType, String propertyName, Object value) {
Neo4jPersistentProperty persistentProperty = getPersistentProperty(indexedType, propertyName);
if (persistentProperty==null) throw new InvalidDataAccessApiUsageException("Unknown Property "+propertyName+" for "+indexedType);
return getSchemaIndexProvider().findByIndexedValue(persistentProperty, value);
}
@Override
public <T extends PropertyContainer> Index<T> getIndex(String indexName, Class<?> indexedType) {
final Neo4jPersistentEntityImpl<?> persistentEntity = indexedType==null ? null : getPersistentEntity(indexedType);
@@ -631,6 +636,9 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationContextAware {
public <T extends PropertyContainer> Index<T> getIndex(Class<?> indexedType, String propertyName) {
final Neo4jPersistentProperty property = getPersistentProperty(indexedType, propertyName);
if (property == null) return getIndexProvider().getIndex(getPersistentEntity(indexedType), null);
if (property.isIndexed() && property.getIndexInfo().isLabelBased()) {
throw new InvalidDataAccessApiUsageException("Can lookup label based property from legacy index");
}
return getIndexProvider().getIndex(property, indexedType);
}

View File

@@ -4,11 +4,12 @@ import org.neo4j.graphdb.Node;
import org.neo4j.helpers.collection.MapUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.core.GraphDatabase;
import org.springframework.data.neo4j.mapping.IndexInfo;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.conversion.EntityResultConverter;
import org.springframework.data.neo4j.support.query.CypherQueryEngine;
import java.util.Collection;
@@ -52,18 +53,23 @@ public class SchemaIndexProvider {
return property.getIndexInfo().getIndexName();
}
public <T> EndResult<T> findAll(Neo4jPersistentEntity entity) {
public <T> Result<T> findAll(Neo4jPersistentEntity entity) {
String label = entity.getTypeAlias().toString();
String query = findByLabelQuery(label);
return cypher.query(query, null).<T>to(entity.getType());
}
public <T> EndResult<T> findAll(Neo4jPersistentProperty property, Object value) {
public <T> Result<T> findByIndexedValue(Neo4jPersistentProperty property, Object value) {
Result<Node> results = findAllNodes(property, value);
return results.<T>to((Class<T>) property.getOwner().getType());
}
private Result<Node> findAllNodes(Neo4jPersistentProperty property, Object value) {
IndexInfo indexInfo = property.getIndexInfo();
String label = indexInfo.getIndexName();
String prop = getName(property);
String query = findByLabelAndPropertyQuery(label, prop);
return cypher.query(query, map("value", value)).<T>to((Class<T>)property.getOwner().getType());
return cypher.query(query, map("value", value)).to(Node.class);
}
private String findByLabelQuery(String label) {
@@ -100,7 +106,4 @@ public class SchemaIndexProvider {
return "CREATE INDEX ON :`"+ label +"`(`"+ prop +"`)";
}
interface IndexCreator {
void deferCreateIndex(Neo4jPersistentProperty property);
}
}

View File

@@ -23,7 +23,6 @@ import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.conversion.ResultConverter;
import org.springframework.data.neo4j.core.GraphDatabase;
@@ -147,6 +146,8 @@ public interface Neo4jOperations {
<R> R createRelationshipBetween(Object start, Object end, Class<R> relationshipEntityClass, String relationshipType, boolean allowDuplicates);
<T> Result<T> findByIndexedValue(Class<? extends T> indexedType, String propertyName, Object value);
/**
* Retrieves an existing index for the given class and/or name
* @param indexName might be null
@@ -239,7 +240,7 @@ public interface Neo4jOperations {
* Provides all instances of a given entity type using the typerepresentation strategy configured for this template.
* This method is also provided by the appropriate repository.
*/
<T> EndResult<T> findAll(Class<T> entityClass);
<T> Result<T> findAll(Class<T> entityClass);
/**
* Provies the instance count a given entity type using the typerepresentation strategy configured for this template.

View File

@@ -26,7 +26,7 @@ import org.springframework.data.geo.Polygon;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.annotation.QueryResult;
import org.springframework.data.neo4j.annotation.ResultColumn;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.model.Group;
import org.springframework.data.neo4j.model.Person;
import org.springframework.data.neo4j.model.Personality;
@@ -107,7 +107,7 @@ public interface PersonRepository extends GraphRepository<Person>, NamedIndexRep
@Query("start person=node:`name-index`('name:*') return person.name as name, person order by name asc ")
Iterable<NameAndPersonResult> getAllNamesAndPeople();
EndResult<Person> findByHeight( short height );
Result<Person> findByHeight(short height);
@QueryResult
interface NameAndPersonResult

View File

@@ -19,7 +19,7 @@ package org.springframework.data.neo4j.repositories;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.model.Person;
import org.springframework.data.neo4j.repository.GraphRepository;
@@ -32,7 +32,7 @@ public interface RedeclaringRepositoryMethodsRepository extends GraphRepository<
* Should not find any persons at all.
*/
@Query("MATCH (n:Person) WHERE n.name='Bubu' return n")
EndResult<Person> findAll();
Result<Person> findAll();
/**
* Should only find persons with the name 'Oliver'.

View File

@@ -25,12 +25,11 @@ import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.index.Index;
import org.neo4j.helpers.collection.IteratorUtil;
import org.neo4j.test.ImpermanentGraphDatabase;
import org.neo4j.test.TestGraphDatabaseFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.model.Group;
import org.springframework.data.neo4j.model.Person;
import org.springframework.data.neo4j.repositories.GroupRepository;
@@ -65,7 +64,7 @@ public class NoIndexDerivedFinderTests {
@Test @Transactional
public void findAllInitiallyWithoutIndexCreation() {
EndResult<Person> result = personRepository.findByHeight( (short) 100 );
Result<Person> result = personRepository.findByHeight((short) 100);
assertEquals(0,IteratorUtil.count( result ));
}

View File

@@ -23,7 +23,7 @@ import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.model.Person;
import org.springframework.data.neo4j.repositories.RedeclaringRepositoryMethodsRepository;
import org.springframework.transaction.annotation.Transactional;
@@ -61,7 +61,7 @@ public class RedeclaringRepositoryMethodsTests extends AbstractEntityBasedGraphR
repository.save(new Person("Oliver", 30));
repository.save(new Person("Thomas", 30));
EndResult<Person> result = repository.findAll();
Result<Person> result = repository.findAll();
assertThat(result.iterator().hasNext(), is(false));
}

View File

@@ -29,7 +29,7 @@ import org.neo4j.helpers.collection.IteratorUtil;
import org.neo4j.helpers.collection.MapUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.mapping.ManagedEntity;
import org.springframework.data.neo4j.model.Friendship;
@@ -38,7 +38,6 @@ import org.springframework.data.neo4j.model.Named;
import org.springframework.data.neo4j.model.Person;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.neo4j.support.query.CypherQueryEngine;
import org.springframework.data.neo4j.support.query.QueryEngine;
import org.springframework.data.neo4j.template.Neo4jOperations;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -360,7 +359,7 @@ public class EntityNeo4jTemplateTests extends EntityTestBase {
@Test @Transactional
public void testConvert() throws Exception {
final EndResult<Group> groups = neo4jOperations.convert(Arrays.asList(getNodeState(testTeam.sdg))).to(Group.class);
final Result<Group> groups = neo4jOperations.convert(Arrays.asList(getNodeState(testTeam.sdg))).to(Group.class);
assertEquals(testTeam.sdg.getName(),groups.iterator().next().getName());
}
@@ -384,9 +383,24 @@ public class EntityNeo4jTemplateTests extends EntityTestBase {
final Person found = neo4jOperations.lookup(Person.class, "name","name:Michael").to(Person.class).single();
assertEquals(testTeam.michael.getId(),found.getId());
}
@Test @Transactional
public void testLookupExact() throws Exception {
final Person found = neo4jOperations.lookup(Person.class, "name","Michael").to(Person.class).single();
assertEquals(testTeam.michael.getId(),found.getId());
}
@Test(expected = InvalidDataAccessApiUsageException.class)
@Transactional
public void testLookupExactLabelIndex() throws Exception {
final Person found = neo4jOperations.lookup(Person.class, "alias","michaelAlias").to(Person.class).single();
assertEquals(testTeam.michael.getId(),found.getId());
}
@Test
@Transactional
public void testFindAllSchemaIndex() throws Exception {
final Person found = neo4jOperations.findByIndexedValue(Person.class, "alias", "michaelAlias").single();
assertEquals(testTeam.michael.getId(),found.getId());
}
}