From d19edc281542b4827070ca10e083e3e52bcad5aa Mon Sep 17 00:00:00 2001 From: Gerrit Meier Date: Tue, 3 Mar 2020 16:51:47 +0100 Subject: [PATCH] DATAGRAPH-1300 - Change query paramater style. Use the $-style instead of the deprecated {}. --- .../data/neo4j/repository/query/Query.java | 2 +- .../filter/DistanceComparisonBuilder.java | 4 +- .../spel/Neo4jQueryPlaceholderSupplier.java | 2 +- .../friends/repo/FriendshipRepository.java | 2 +- .../movies/repo/CinemaRepository.java | 4 +- .../movies/repo/RatingRepository.java | 2 +- .../examples/movies/repo/UserRepository.java | 38 +++++++++---------- .../repository/sample/UserRepository.java | 2 +- .../META-INF/neo4j-named-queries.properties | 8 ++-- .../reference/neo4j-repositories.adoc | 36 +++++++++--------- 10 files changed, 50 insertions(+), 50 deletions(-) diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/Query.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/Query.java index 31d3214a5..53ab2eed0 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/Query.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/Query.java @@ -39,7 +39,7 @@ public class Query { private static final String SKIP = "sdnSkip"; private static final String LIMIT = "sdnLimit"; - private static final String SKIP_LIMIT = " SKIP {" + SKIP + "} LIMIT {" + LIMIT + "}"; + private static final String SKIP_LIMIT = " SKIP $" + SKIP + " LIMIT $" + LIMIT; private static final String ORDER_BY_CLAUSE = " ORDER BY %s"; private Filters filters; diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/filter/DistanceComparisonBuilder.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/filter/DistanceComparisonBuilder.java index 3bef8a320..6831e4756 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/filter/DistanceComparisonBuilder.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/filter/DistanceComparisonBuilder.java @@ -153,8 +153,8 @@ class DistanceComparisonBuilder extends FilterBuilder { String longitudeProperty = nodeIdentifier + ".longitude"; return String.format( - "distance(coalesce(point({latitude: %s, longitude: %s}), %s), point({latitude:{lat}, longitude:{lon}})) " - + "%s {distance} ", + "distance(coalesce(point({latitude: %s, longitude: %s}), %s), point({latitude:$lat, longitude:$lon})) " + + "%s $distance ", latitudeProperty, longitudeProperty, nodeIdentifier + "." + propertyName(), ComparisonOperator.LESS_THAN.getValue()); } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/spel/Neo4jQueryPlaceholderSupplier.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/spel/Neo4jQueryPlaceholderSupplier.java index 070d630ff..0d38a7e84 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/spel/Neo4jQueryPlaceholderSupplier.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/spel/Neo4jQueryPlaceholderSupplier.java @@ -31,6 +31,6 @@ public class Neo4jQueryPlaceholderSupplier implements PlaceholderSupplier { @Override public String decoratePlaceholder(String placeholder) { - return "{" + placeholder + "}"; + return "$" + placeholder; } } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/friends/repo/FriendshipRepository.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/friends/repo/FriendshipRepository.java index 794f4fef7..5308476c3 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/friends/repo/FriendshipRepository.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/friends/repo/FriendshipRepository.java @@ -25,7 +25,7 @@ import org.springframework.data.neo4j.repository.Neo4jRepository; */ public interface FriendshipRepository extends Neo4jRepository { - @Query("MATCH (person1)-[rel:IS_FRIEND]->(person2) WHERE ID(person1)={0} AND ID(person2)={1} return rel") + @Query("MATCH (person1)-[rel:IS_FRIEND]->(person2) WHERE ID(person1)=$0 AND ID(person2)=$1 return rel") Friendship getFriendship(Person person1, Person person2); } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/CinemaRepository.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/CinemaRepository.java index 7e955925c..f8ac914b3 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/CinemaRepository.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/CinemaRepository.java @@ -101,8 +101,8 @@ public interface CinemaRepository extends Neo4jRepository { @Query(value = "MATCH (n:Theatre) RETURN n", countQuery = "MATCH (n:Theatre) return count(*)") Page getPagedCinemaQueryResultInterfaces(Pageable pageable); - @Query(value = "MATCH (n:Theatre {city:{city}}) RETURN n ORDER BY n.name", - countQuery = "MATCH (n:Theatre {city:{city}}) return count(*)") + @Query(value = "MATCH (n:Theatre {city:$city}) RETURN n ORDER BY n.name", + countQuery = "MATCH (n:Theatre {city:$city}) return count(*)") Page getPagedCinemasByCityWithPageCount(@Param("city") String city, Pageable pageable); @Query("MATCH (n:Theatre) RETURN n") 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 9792f4081..7ff7f691a 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 @@ -59,6 +59,6 @@ public interface RatingRepository extends Neo4jRepository { List deleteByStarsOrRatingTimestampGreaterThan(int stars, long ratingTimestamp); - @Query("MATCH (a)-[r:RATED]-(b) WHERE ID(a)={0} and ID(b)={1} RETURN a,r,b") + @Query("MATCH (a)-[r:RATED]-(b) WHERE ID(a)=$0 and ID(b)=$1 RETURN a,r,b") Rating findRatingByUserAndTempMovie(long userId, long tempMovieId); } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/UserRepository.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/UserRepository.java index fce5e01a6..bf4f9e248 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/UserRepository.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/movies/repo/UserRepository.java @@ -69,40 +69,40 @@ public interface UserRepository extends PersonRepository { @Query("MATCH (m:Movie)<-[:ACTED_IN]-(a:User) RETURN m.name as movie, collect(a.name) as cast") List> getGraph(); - @Query("MATCH (user:User{name:{name}}) RETURN user") + @Query("MATCH (user:User{name:$name}) RETURN user") User findUserByNameWithNamedParam(@Param("name") String name); - @Query("MATCH (user:User{name:{name}}) RETURN user") + @Query("MATCH (user:User{name:$name}) RETURN user") User findUserByNameWithNamedParamWithoutParamAnnotation(String name); - @Query("MATCH (user:User{name:{0}}) RETURN user") + @Query("MATCH (user:User{name:$0}) RETURN user") User findUserByName(String name); @Query("MATCH (user:User) RETURN id(user) AS userId, id(user) as id, user.name AS userName, user.age ORDER BY user.age") Iterable retrieveAllUsersAndTheirAges(); - @Query("MATCH (user:User{name:{0}}) RETURN user.name AS name") + @Query("MATCH (user:User{name:$0}) RETURN user.name AS name") UnmanagedUserPojo findIndividualUserAsDifferentObject(String name); - @Query("MATCH (user:User) WHERE user.name={0} RETURN user.name AS name, user.age AS ageOfUser") + @Query("MATCH (user:User) WHERE user.name=$0 RETURN user.name AS name, user.age AS ageOfUser") UserQueryResultObject findIndividualUserAsProxiedObject(String name); - @Query("MATCH (user:User) WHERE user.name={0} RETURN user as user, user.age AS ageOfUser") + @Query("MATCH (user:User) WHERE user.name=$0 RETURN user as user, user.age AS ageOfUser") UserQueryResultObject findWrappedUserAsProxiedObject(String name); - @Query("MATCH (user:User) WHERE user.gender={0} RETURN user.name AS userName, user.gender AS userGender, user.account as userAccount, user.yearOfBirth as yearOfBirth, user.yearOfBirth as plainYearValue, user.deposits as userDeposits") + @Query("MATCH (user:User) WHERE user.gender=$0 RETURN user.name AS userName, user.gender AS userGender, user.account as userAccount, user.yearOfBirth as yearOfBirth, user.yearOfBirth as plainYearValue, user.deposits as userDeposits") Iterable findUsersByGender(Gender gender); - @Query("MATCH (user:User) WHERE user.name={0} RETURN user") + @Query("MATCH (user:User) WHERE user.name=$0 RETURN user") EntityWrappingQueryResult findWrappedUserByName(String userName); - @Query("MATCH (user:User)-[:FRIEND_OF]->(f) WHERE user.name={0} RETURN user, collect(f) as friends") + @Query("MATCH (user:User)-[:FRIEND_OF]->(f) WHERE user.name=$0 RETURN user, collect(f) as friends") EntityWrappingQueryResult findWrappedUserAndFriendsDepth0(String userName); - @Query("MATCH (user:User)-[r:FRIEND_OF]->(f) WHERE user.name={0} RETURN user, collect(r) as rels, collect(f) as friends") + @Query("MATCH (user:User)-[r:FRIEND_OF]->(f) WHERE user.name=$0 RETURN user, collect(r) as rels, collect(f) as friends") EntityWrappingQueryResult findWrappedUserAndFriendsDepth1(String userName); - @Query("MATCH (user:User)-[r:RATED]->(m) WHERE user.name={0} RETURN user, collect(r) as ratings, collect(m) as movies, avg(r.stars) as avgRating") + @Query("MATCH (user:User)-[r:RATED]->(m) WHERE user.name=$0 RETURN user, collect(r) as ratings, collect(m) as movies, avg(r.stars) as avgRating") EntityWrappingQueryResult findWrappedUserAndRatingsByName(String userName); @Query("MATCH (user:User)-[r:RATED]->(m) RETURN user, collect(r) as ratings, collect(m) as movies, avg(r.stars) as avgRating order by user.name desc") @@ -111,16 +111,16 @@ public interface UserRepository extends PersonRepository { @Query("MATCH (user:User) RETURN ID(user)") List getUserNodeIds(); - @Query("MATCH (user:User) WHERE ID(user)={0} return user") + @Query("MATCH (user:User) WHERE ID(user)=$0 return user") User loadUserById(User user); - @Query("MATCH (user:User) WHERE ID(user)={userId} RETURN user") + @Query("MATCH (user:User) WHERE ID(user)=$userId RETURN user") User loadUserByNamedId(@Param("userId") User user); @Query("MATCH (user:User) RETURN user") Iterable getAllUsersIterable(); - @Query("MATCH (user:User) set user.name={0}") + @Query("MATCH (user:User) set user.name=$0") void setNamesNull(String name); List findByNameIsNotLike(String name); @@ -157,7 +157,7 @@ public interface UserRepository extends PersonRepository { @Query("MATCH (user:User) WHERE user.name=?#{[0]} RETURN user") User findUserByNameUsingSpElWithIndex(String name); - @Query("MATCH (user:User) WHERE user.name=:#{[0]} and user.name=:#{[0]}RETURN user") + @Query("MATCH (user:User) WHERE user.name=:#{[0]} and user.name=:#{[0]} RETURN user") User findUserByNameUsingSpElWithIndexColon(String name); @Query("MATCH (user:User) WHERE user.age=?#{5 + 5} RETURN user") @@ -169,13 +169,13 @@ public interface UserRepository extends PersonRepository { @Query("MATCH (user:User) WHERE user.name=:#{'Michal'} RETURN user") User findUserByNameAndMiddleNameUsingSpElWithValue(); - @Query("MATCH (user:User) WHERE user.name=?#{[0]} and user.surname={name} RETURN user") + @Query("MATCH (user:User) WHERE user.name=?#{[0]} and user.surname=$name RETURN user") User findUserByNameAndSurnameUsingSpElIndexAndPlaceholderWithOneParameter(@Param("name") String queryName); - @Query("MATCH (user:User) WHERE user.name=:#{#name} and user.surname={name} RETURN user") + @Query("MATCH (user:User) WHERE user.name=:#{#name} and user.surname=$name RETURN user") User findUserByNameAndSurnameUsingSpElPropertyAndPlaceholderWithOneParameter(@Param("name") String queryName); - @Query("MATCH (user:User) WHERE user.name=:#{#name} and user.surname={name} RETURN user") + @Query("MATCH (user:User) WHERE user.name=:#{#name} and user.surname=$name RETURN user") User findUserByNameAndSurnameUsingSpElPropertyAndIndexWithOneParameter(@Param("name") String queryName); @Query("MATCH (user:User) WHERE user.name=:#{#name} and user.surname=:#{#name} RETURN user") @@ -184,6 +184,6 @@ public interface UserRepository extends PersonRepository { @Query("MATCH (user:User) WHERE user.name=:#{#name} and user.surname=:#{[0]} RETURN user") User findUserByNameAndSurnameUsingSpElPropertyAndSpElIndex(@Param("name") String queryName); - @Query("MATCH (user:User) WHERE user.name={name} and user.name={0} and user.name=:#{#name} and user.name=:#{[0]} RETURN user") + @Query("MATCH (user:User) WHERE user.name=$name and user.name=$0 and user.name=:#{#name} and user.name=:#{[0]} RETURN user") User findUserByNameUsingNativeIndexAndNameAndSpElNameAndSpElIndex(@Param("name") String queryName); } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/sample/UserRepository.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/sample/UserRepository.java index bccf2d529..bd9df923a 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/sample/UserRepository.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/sample/UserRepository.java @@ -72,7 +72,7 @@ public interface UserRepository extends Neo4jRepository { * @param emailAddress * @return */ - @Query("MATCH (n:User{emailAddress:{emailAddress}}) return n") + @Query("MATCH (n:User{emailAddress:$emailAddress}) return n") @Transactional(readOnly = true) User findByAnnotatedQuery(@Param("emailAddress") String emailAddress); } diff --git a/spring-data-neo4j/src/test/resources/META-INF/neo4j-named-queries.properties b/spring-data-neo4j/src/test/resources/META-INF/neo4j-named-queries.properties index d1c895185..233b18bbb 100644 --- a/spring-data-neo4j/src/test/resources/META-INF/neo4j-named-queries.properties +++ b/spring-data-neo4j/src/test/resources/META-INF/neo4j-named-queries.properties @@ -1,5 +1,5 @@ SampleEntityForNamedQuery.findByQueryWithoutParameter=MATCH (e) WHERE e.name='test' RETURN e -SampleEntityForNamedQuery.findByQueryWithParameter=MATCH (e) WHERE e.name={name} RETURN e -SampleEntityForNamedQuery.findByPagedQueryWithParameter=MATCH (e) WHERE e.name={name} RETURN e -SampleEntityForNamedQuery.findByPagedQueryWithParameter.countQuery=MATCH (e) WHERE e.name={name} RETURN count(e) -SampleEntityForNamedQuery.findByPagedQueryWithoutCountQuery=MATCH (e) WHERE e.name={name} RETURN e +SampleEntityForNamedQuery.findByQueryWithParameter=MATCH (e) WHERE e.name=$name RETURN e +SampleEntityForNamedQuery.findByPagedQueryWithParameter=MATCH (e) WHERE e.name=$name RETURN e +SampleEntityForNamedQuery.findByPagedQueryWithParameter.countQuery=MATCH (e) WHERE e.name=$name RETURN count(e) +SampleEntityForNamedQuery.findByPagedQueryWithoutCountQuery=MATCH (e) WHERE e.name=$name RETURN e diff --git a/src/main/asciidoc/reference/neo4j-repositories.adoc b/src/main/asciidoc/reference/neo4j-repositories.adoc index 8d9537e2c..54a472d59 100644 --- a/src/main/asciidoc/reference/neo4j-repositories.adoc +++ b/src/main/asciidoc/reference/neo4j-repositories.adoc @@ -230,10 +230,10 @@ Depending on the `Range` definition `n.score >= min AND n.score \<= max` or Queries using the Cypher graph query language can be supplied with the `@Query` annotation. That means a repository method annotated with + -`@Query("MATCH (:Actor {name:{name}})-[:ACTED_IN]\->(m:Movie) return m")` + +`@Query("MATCH (:Actor {name:$name})-[:ACTED_IN]\->(m:Movie) return m")` + will use the supplied query to retrieve data from Neo4j. -The named or indexed parameter `{param}` will be substituted by the actual method parameter. +The named or indexed parameter `$param` will be substituted by the actual method parameter. Node and relationship entities are handled directly and converted into their respective ids. All other parameters types are provided directly (i.e. `String`, `Long`, etc.). @@ -254,7 +254,7 @@ Instead, return nodes and relationships to have them mapped to domain entities. Sometimes it makes sense to extract e.g. a long query. Spring Data Neo4j will look in the `META-INF/neo4j-named-queries.properties` file to find named queries. -If you provide a query property like `User.findByQuery=MATCH (e) WHERE e.name={name} RETURN e` you can refer to this method by providing a finder method in your repository. +If you provide a query property like `User.findByQuery=MATCH (e) WHERE e.name=$name RETURN e` you can refer to this method by providing a finder method in your repository. The repository has to support the given entity type (in this example `User`) and the method has to be named as the defined one (`findByQuery`). As you can see in the example it is possible to parameterize the query. Named count query can be specified by adding `.countQuery` suffix to the related query property key. For example, if the next query should return paged result `User.findAllByQuery=MATCH (e) RETURN e`, the count query can be specified by the following way: `User.findAllByQuery.countQuery=MATCH (e) RETURN count(e)`. @@ -290,38 +290,38 @@ as described in the <>) section. public interface MovieRepository extends Neo4jRepository { // returns the node with id equal to idOfMovie parameter - @Query("MATCH (n) WHERE id(n)={0} RETURN n") + @Query("MATCH (n) WHERE id(n)=$0 RETURN n") Movie getMovieFromId(Integer idOfMovie); // returns the nodes which have a title according to the movieTitle parameter - @Query("MATCH (movie:Movie {title={0}}) RETURN movie") + @Query("MATCH (movie:Movie {title=$0}) RETURN movie") Movie getMovieFromTitle(String movieTitle); // same with optional result - @Query("MATCH (movie:Movie {title={0}}) RETURN movie") + @Query("MATCH (movie:Movie {title=$0}) RETURN movie") Optional getMovieFromTitle(String movieTitle); // returns a Page of Actors that have a ACTS_IN relationship to the movie node with the title equal to movieTitle parameter. - @Query(value = "MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor", countQuery= "MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN count(actor)") + @Query(value = "MATCH (movie:Movie {title=$0})<-[:ACTS_IN]-(actor) RETURN actor", countQuery= "MATCH (movie:Movie {title=$0})<-[:ACTS_IN]-(actor) RETURN count(actor)") Page getActorsThatActInMovieFromTitle(String movieTitle, PageRequest page); // returns a Page of Actors that have a ACTS_IN relationship to the movie node with the title equal to movieTitle parameter with an accurate total count - @Query(value = "MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor", countQuery = "MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN count(*)") + @Query(value = "MATCH (movie:Movie {title=$0})<-[:ACTS_IN]-(actor) RETURN actor", countQuery = "MATCH (movie:Movie {title=$0})<-[:ACTS_IN]-(actor) RETURN count(*)") Page getActorsThatActInMovieFromTitle(String movieTitle, Pageable page); // returns a Slice of Actors that have a ACTS_IN relationship to the movie node with the title equal to movieTitle parameter. - @Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor") + @Query("MATCH (movie:Movie {title=$0})<-[:ACTS_IN]-(actor) RETURN actor") Slice getActorsThatActInMovieFromTitle(String movieTitle, Pageable page); // returns users who rated a movie (movie parameter) higher than rating (rating parameter) @Query("MATCH (movie:Movie)<-[r:RATED]-(user) " + - "WHERE id(movie)={movieId} AND r.stars > {rating} " + + "WHERE id(movie)=$movieId AND r.stars > {rating} " + "RETURN user") Iterable getUsersWhoRatedMovieFromTitle(@Param("movieId") Movie movie, @Param("rating") Integer rating); // returns users who rated a movie based on movie title (movieTitle parameter) higher than rating (rating parameter) - @Query("MATCH (movie:Movie {title:{0}})<-[r:RATED]-(user) " + - "WHERE r.stars > {1} " + + @Query("MATCH (movie:Movie {title:$0})<-[r:RATED]-(user) " + + "WHERE r.stars > $1 " + "RETURN user") Iterable getUsersWhoRatedMovieFromTitle(String movieTitle, Integer rating); @@ -342,21 +342,21 @@ The parameters will be used in the order they appear in the method signature so ---- public interface PersonRepository extends Neo4jRepository { - // MATCH (person:Person {name={0}}) RETURN person + // MATCH (person:Person {name=$0}) RETURN person Person findByName(String name); // MATCH (person:Person) - // WHERE person.age = {0} AND person.married = {1} + // WHERE person.age = $0 AND person.married = $1 // RETURN person Iterable findByAgeAndMarried(int age, boolean married); // MATCH (person:Person) - // WHERE person.age = {0} - // RETURN person ORDER BY person.name SKIP {skip} LIMIT {limit} + // WHERE person.age = $0 + // RETURN person ORDER BY person.name SKIP $skip LIMIT $limit Page findByAge(int age, Pageable pageable); // MATCH (person:Person) - // WHERE person.age = {0} + // WHERE person.age = $0 // RETURN person ORDER BY person.name List findByAge(int age, Sort sort); @@ -388,7 +388,7 @@ Please keep in mind that Java and Cypher are case-sensitive. public interface MovieRepository extends Neo4jRepository { @Query("MATCH (movie:Movie)-[r:RATING]->(), (movie)<-[:ACTS_IN]-(actor:Actor) " + - "WHERE movie.id={0} " + + "WHERE movie.id=$0 " + "RETURN movie as movie, COLLECT(actor) AS cast, AVG(r.stars) AS averageRating") MovieData getMovieData(String movieId); }