diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/derived/DerivedGraphRepositoryQuery.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/derived/DerivedGraphRepositoryQuery.java index eb63ef9b0f..c4b680db50 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/derived/DerivedGraphRepositoryQuery.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/derived/DerivedGraphRepositoryQuery.java @@ -13,20 +13,19 @@ package org.springframework.data.neo4j.repository.query.derived; -import java.util.*; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import org.neo4j.ogm.cypher.Filter; import org.neo4j.ogm.cypher.Filters; import org.neo4j.ogm.cypher.function.DistanceComparison; import org.neo4j.ogm.cypher.function.DistanceFromPoint; import org.neo4j.ogm.cypher.function.FilterFunction; -import org.neo4j.ogm.cypher.query.AbstractRequest; import org.neo4j.ogm.cypher.query.Pagination; import org.neo4j.ogm.cypher.query.SortOrder; -import org.neo4j.ogm.model.Result; -import org.neo4j.ogm.session.Neo4jSession; import org.neo4j.ogm.session.Session; -import org.neo4j.ogm.session.request.strategy.VariableDepthQuery; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.SliceImpl; @@ -58,7 +57,7 @@ public class DerivedGraphRepositoryQuery implements RepositoryQuery { private final PartTree tree; protected final Session session; - protected final EntityMetadata info; + protected final EntityMetadata info; private final int DEFAULT_QUERY_DEPTH = 1; @@ -91,21 +90,11 @@ class CountByQuery implements RepositoryQuery { @Override public Object execute(Object[] parameters) { - Class domainClass = info.getJavaType(); - if (getQueryMethod().getReturnedObjectType().equals(Long.class)) { - String label = ((Neo4jSession) session).metaData().classInfo(domainClass.getName()).neo4jName(); Filters filters = resolveParams(parameters); - - // TODO? create a specific implementation, e.g. CountQuery().findByProperties(label, filters) - AbstractRequest query = new VariableDepthQuery().findByProperties(label, filters, 0); - - String statement = query.getStatement().replace("RETURN n", "RETURN COUNT(n)"); - Result result = session.query(statement, query.getParameters()); - Map resultMap = result.iterator().next(); - return Long.parseLong(resultMap.get("COUNT(n)").toString()); + return session.count(info.getJavaType(), filters); } else { - throw new RuntimeException("Count queries must return a Long"); + throw new RuntimeException("Long is required as the return type of a Count query"); } } @@ -120,35 +109,18 @@ class DeleteByQuery implements RepositoryQuery { @Override public Object execute(Object[] parameters) { - Class domainClass = info.getJavaType(); - String label = ((Neo4jSession) session).metaData().classInfo(domainClass.getName()).neo4jName(); Filters filters = resolveParams(parameters); - // TODO? create a specific implementation, e.g. DeleteQuery().findByProperties(label, filters) - AbstractRequest query = new VariableDepthQuery().findByProperties(label, filters, 0); - Class returnType = graphQueryMethod.resolveConcreteReturnType(); - String statement = query.getStatement(); if (returnType.equals(Long.class)) { - if (graphQueryMethod.isCollectionQuery()) { - statement = statement.replace("RETURN n", "OPTIONAL MATCH (n)-[r]-() DELETE r, n RETURN id(n)"); - Result result = session.query(statement, query.getParameters()); - List deletedIds = new ArrayList(); - for (Map resultEntry : result) { - deletedIds.add(Long.parseLong(resultEntry.get("id(n)").toString())); - } - return deletedIds; + return session.delete(info.getJavaType(), filters, true); // list deleted ids + } else { + return session.delete(info.getJavaType(), filters, false); // count deleted ids } - - statement = statement.replace("RETURN n", "OPTIONAL MATCH (n)-[r]-() DELETE r, n RETURN COUNT(n)"); - Result result = session.query(statement, query.getParameters()); - Map resultMap = result.iterator().next(); - return Long.parseLong(resultMap.get("COUNT(n)").toString()); } - - throw new RuntimeException("Return type of Delete query must Long or Iterable"); + throw new RuntimeException("Long or Iterable is required as the return type of a Delete query"); } @Override @@ -391,4 +363,5 @@ int configuration() { return NO_PAGING_OR_SORTING; } } + } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/RatingRepository.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/RatingRepository.java index 4cd10215dd..a7bc58e710 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/RatingRepository.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/RatingRepository.java @@ -13,11 +13,11 @@ package org.springframework.data.neo4j.examples.movies.repo; +import java.util.List; + import org.springframework.data.neo4j.examples.movies.domain.Rating; import org.springframework.data.neo4j.repository.GraphRepository; -import java.util.List; - /** * @author Luanne Misquitta */ @@ -49,4 +49,10 @@ public interface RatingRepository extends GraphRepository { List findByUserNameAndUserMiddleName(String username, String middleName); + Long countByStars(int stars); + + Long removeByUserName(String username); + + List deleteByStarsOrRatingTimestampGreaterThan(int stars, long ratingTimestamp); + } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/queries/DerivedRelationshipEntityQueryIT.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/queries/DerivedRelationshipEntityQueryIT.java index ade0bca058..6578f89963 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/queries/DerivedRelationshipEntityQueryIT.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/queries/DerivedRelationshipEntityQueryIT.java @@ -393,4 +393,98 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } }); } + + /** + * @see DATAGRAPH-813 + */ + @Test + @Transactional + public void shouldDeleteAndReturnDeletedIds() { + User critic = new User("Gary"); + TempMovie film = new TempMovie("Fast and Furious XVII"); + Rating filmRating = critic.rate(film, 2, "They've made far too many of these films now!"); + filmRating.setRatingTimestamp(1000); + + userRepository.save(critic); + + List ratingIds = ratingRepository.deleteByStarsOrRatingTimestampGreaterThan(2, 500); + assertEquals(filmRating.getId(), ratingIds.get(0)); + assertEquals(1, ratingIds.size()); + + List ratings = ratingRepository.findByStarsAndRatingTimestamp(2, 2000); + assertEquals(0, ratings.size()); + } + + /** + * @see DATAGRAPH-813 + */ + @Test + @Transactional + public void shouldCountByStars() { + User critic = new User("Gary"); + TempMovie film = new TempMovie("Fast and Furious XVII"); + Rating filmRating = critic.rate(film, 2, "They've made far too many of these films now!"); + filmRating.setRatingTimestamp(1000); + + userRepository.save(critic); + + long starredRatings = ratingRepository.countByStars(2); + assertEquals(1L, starredRatings); + + } + + /** + * @see DATAGRAPH-813 + */ + @Test + @Transactional + public void shouldRemoveByUserNameAndReturnCountOfDeletedObjects() { + User critic = new User("Gary"); + TempMovie film = new TempMovie("Fast and Furious XVII"); + Rating filmRating = critic.rate(film, 2, "They've made far too many of these films now!"); + filmRating.setRatingTimestamp(1000); + + userRepository.save(critic); + + long countRemovedObjects = ratingRepository.removeByUserName("Gary"); + assertEquals(1L, countRemovedObjects); + + } + + /** + * @see DATAGRAPH-813 + */ + @Test + @Transactional + public void shouldCountNothingWithNonMatchingFilter() { + User critic = new User("Gary"); + TempMovie film = new TempMovie("Fast and Furious XVII"); + Rating filmRating = critic.rate(film, 2, "They've made far too many of these films now!"); + filmRating.setRatingTimestamp(1000); + + userRepository.save(critic); + + long countRemovedObjects = ratingRepository.removeByUserName("Bill"); + assertEquals(0L, countRemovedObjects); + + } + + /** + * @see DATAGRAPH-813 + */ + @Test + @Transactional + public void shouldDeleteNothingWithNonMatchingFilter() { + User critic = new User("Gary"); + TempMovie film = new TempMovie("Fast and Furious XVII"); + Rating filmRating = critic.rate(film, 2, "They've made far too many of these films now!"); + filmRating.setRatingTimestamp(1000); + + userRepository.save(critic); + + List deletedIds = ratingRepository.deleteByStarsOrRatingTimestampGreaterThan(3, 2000); + assertEquals(0L, deletedIds.size()); + + } + } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repositories/ProgrammaticRepositoryIT.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repositories/ProgrammaticRepositoryIT.java index ebf2c87c4a..29d5beb859 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repositories/ProgrammaticRepositoryIT.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repositories/ProgrammaticRepositoryIT.java @@ -159,10 +159,6 @@ public void shouldDeleteUserByNameAndReturnListOfDeletedUserIds() { Assert.assertEquals(0, userRepository.count()); - // TODO ?? - // ensure that the ID field of deleted user objects is set to null; - - } @Test