From 9fd0e475149c9ebc16d750f20119c45cda69750e Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Mon, 1 Aug 2022 14:37:03 +0200 Subject: [PATCH] Support Contains with ElementCollection of type String. Properly handle `contains` for an ElementCollection of type String in a LIKE query, wrapping the the parameter in wildcards only when needed. Closes: #2607. --- .../query/ParameterMetadataProvider.java | 4 +++- .../jpa/repository/UserRepositoryTests.java | 18 ++++++++++++++++++ .../jpa/repository/sample/UserRepository.java | 3 +++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/ParameterMetadataProvider.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/ParameterMetadataProvider.java index 1064c2058..acca0a5dc 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/ParameterMetadataProvider.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/ParameterMetadataProvider.java @@ -196,6 +196,7 @@ class ParameterMetadataProvider { private final ParameterExpression expression; private final EscapeCharacter escape; private final boolean ignoreCase; + private final boolean noWildcards; /** * Creates a new {@link ParameterMetadata}. @@ -206,6 +207,7 @@ class ParameterMetadataProvider { this.expression = expression; this.type = value == null && Type.SIMPLE_PROPERTY.equals(part.getType()) ? Type.IS_NULL : part.getType(); this.ignoreCase = IgnoreCaseType.ALWAYS.equals(part.shouldIgnoreCase()); + this.noWildcards = part.getProperty().getLeafProperty().isCollection(); this.escape = escape; } @@ -241,7 +243,7 @@ class ParameterMetadataProvider { return value; } - if (String.class.equals(expressionType)) { + if (String.class.equals(expressionType) && !noWildcards) { switch (type) { case STARTING_WITH: diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java index 877c8c905..283e45161 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java @@ -2968,6 +2968,24 @@ public class UserRepositoryTests { assertThat(foundData).containsExactly("joachim", "dave", "kevin"); } + @Test // GH-2607 + void containsWithCollection(){ + + firstUser.getAttributes().add("cool"); + firstUser.getAttributes().add("hip"); + + secondUser.getAttributes().add("hip"); + + thirdUser.getAttributes().add("rockstar"); + thirdUser.getAttributes().add("%hip%"); + + flushTestUsers(); + + List result = repository.findByAttributesContains("hip"); + + assertThat(result).containsOnly(firstUser, secondUser); + } + private Page executeSpecWithSort(Sort sort) { flushTestUsers(); diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java index 51659d968..3236ddfa3 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java @@ -676,6 +676,9 @@ public interface UserRepository nativeQuery = true) List complexWithNativeStatement(); + // GH-2607 + List findByAttributesContains(String attribute); + interface RolesAndFirstname { String getFirstname();