Skip to content

Commit 39c745a

Browse files
committed
spring-projects#282 - Add support of 'IS (NOT) NULL' and '(NOT) LIKE' operators
1 parent 61083bf commit 39c745a

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

Diff for: src/main/java/org/springframework/data/r2dbc/repository/query/ConditionFactory.java

+57
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,22 @@ public Condition createCondition(Part part) {
8888
BindMarker bindMarker = createBindMarker(parameterMetadataProvider.next(part));
8989
return Conditions.isLessOrEqualTo(pathExpression, bindMarker);
9090
}
91+
case IS_NULL: {
92+
return Conditions.isNull(createPropertyPathExpression(part.getProperty()));
93+
}
94+
case IS_NOT_NULL: {
95+
return Conditions.isNull(createPropertyPathExpression(part.getProperty())).not();
96+
}
97+
case LIKE: {
98+
Expression pathExpression = createPropertyPathExpression(part.getProperty());
99+
BindMarker bindMarker = createBindMarker(parameterMetadataProvider.next(part));
100+
return Conditions.like(pathExpression, bindMarker);
101+
}
102+
case NOT_LIKE: {
103+
Expression pathExpression = createPropertyPathExpression(part.getProperty());
104+
BindMarker bindMarker = createBindMarker(parameterMetadataProvider.next(part));
105+
return NotLike.create(pathExpression, bindMarker);
106+
}
91107
case SIMPLE_PROPERTY: {
92108
Expression pathExpression = createPropertyPathExpression(part.getProperty());
93109
ParameterMetadata parameterMetadata = parameterMetadataProvider.next(part);
@@ -118,4 +134,45 @@ private BindMarker createBindMarker(ParameterMetadata parameterMetadata) {
118134
}
119135
return SQL.bindMarker();
120136
}
137+
138+
// TODO: include support of NOT LIKE operator into spring-data-relational
139+
private static class NotLike implements Segment, Condition {
140+
private final Comparison delegate;
141+
142+
private NotLike(Expression leftColumnOrExpression, Expression rightColumnOrExpression) {
143+
this.delegate = Comparison.create(leftColumnOrExpression, "NOT LIKE", rightColumnOrExpression);
144+
}
145+
146+
/**
147+
* Creates new instance of this class with the given {@link Expression}s.
148+
*
149+
* @param leftColumnOrExpression the left {@link Expression}
150+
* @param rightColumnOrExpression the right {@link Expression}
151+
* @return {@link NotLike} condition
152+
*/
153+
public static NotLike create(Expression leftColumnOrExpression, Expression rightColumnOrExpression) {
154+
Assert.notNull(leftColumnOrExpression, "Left expression must not be null!");
155+
Assert.notNull(rightColumnOrExpression, "Right expression must not be null!");
156+
return new NotLike(leftColumnOrExpression, rightColumnOrExpression);
157+
}
158+
159+
@Override
160+
public void visit(Visitor visitor) {
161+
Assert.notNull(visitor, "Visitor must not be null!");
162+
delegate.visit(visitor);
163+
}
164+
165+
public Expression getLeft() {
166+
return delegate.getLeft();
167+
}
168+
169+
public Expression getRight() {
170+
return delegate.getRight();
171+
}
172+
173+
@Override
174+
public String toString() {
175+
return getLeft().toString() + " NOT LIKE " + getRight();
176+
}
177+
}
121178
}

Diff for: src/test/java/org/springframework/data/r2dbc/repository/query/PartTreeR2dbcQueryIntegrationTests.java

+52
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,50 @@ public void createsQueryToFindAllEntitiesByDateAttributeBefore() throws Exceptio
215215
assertThat(bindableQuery.get()).isEqualTo(expectedSql);
216216
}
217217

218+
@Test
219+
public void createsQueryToFindAllEntitiesByIntegerAttributeIsNull() throws Exception {
220+
R2dbcQueryMethod queryMethod = getQueryMethod("findAllByAgeIsNull");
221+
PartTreeR2dbcQuery r2dbcQuery = new PartTreeR2dbcQuery(queryMethod, databaseClient, r2dbcConverter,
222+
dataAccessStrategy);
223+
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]);
224+
BindableQuery bindableQuery = r2dbcQuery.createQuery(accessor);
225+
String expectedSql = "SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".age IS NULL";
226+
assertThat(bindableQuery.get()).isEqualTo(expectedSql);
227+
}
228+
229+
@Test
230+
public void createsQueryToFindAllEntitiesByIntegerAttributeIsNotNull() throws Exception {
231+
R2dbcQueryMethod queryMethod = getQueryMethod("findAllByAgeIsNotNull");
232+
PartTreeR2dbcQuery r2dbcQuery = new PartTreeR2dbcQuery(queryMethod, databaseClient, r2dbcConverter,
233+
dataAccessStrategy);
234+
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]);
235+
BindableQuery bindableQuery = r2dbcQuery.createQuery(accessor);
236+
String expectedSql = "SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".age IS NOT NULL";
237+
assertThat(bindableQuery.get()).isEqualTo(expectedSql);
238+
}
239+
240+
@Test
241+
public void createsQueryToFindAllEntitiesByStringAttributeLike() throws Exception {
242+
R2dbcQueryMethod queryMethod = getQueryMethod("findAllByFirstNameLike", String.class);
243+
PartTreeR2dbcQuery r2dbcQuery = new PartTreeR2dbcQuery(queryMethod, databaseClient, r2dbcConverter,
244+
dataAccessStrategy);
245+
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] {"%John%"});
246+
BindableQuery bindableQuery = r2dbcQuery.createQuery(accessor);
247+
String expectedSql = "SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".first_name LIKE ?";
248+
assertThat(bindableQuery.get()).isEqualTo(expectedSql);
249+
}
250+
251+
@Test
252+
public void createsQueryToFindAllEntitiesByStringAttributeNotLike() throws Exception {
253+
R2dbcQueryMethod queryMethod = getQueryMethod("findAllByFirstNameNotLike", String.class);
254+
PartTreeR2dbcQuery r2dbcQuery = new PartTreeR2dbcQuery(queryMethod, databaseClient, r2dbcConverter,
255+
dataAccessStrategy);
256+
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] {"%John%"});
257+
BindableQuery bindableQuery = r2dbcQuery.createQuery(accessor);
258+
String expectedSql = "SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".first_name NOT LIKE ?";
259+
assertThat(bindableQuery.get()).isEqualTo(expectedSql);
260+
}
261+
218262
private R2dbcQueryMethod getQueryMethod(String methodName, Class<?>... parameterTypes) throws Exception {
219263
Method method = UserRepository.class.getMethod(methodName, parameterTypes);
220264
return new R2dbcQueryMethod(method, new DefaultRepositoryMetadata(UserRepository.class),
@@ -247,6 +291,14 @@ private interface UserRepository extends Repository<User, Long> {
247291
Flux<User> findAllByDateOfBirthAfter(Date date);
248292

249293
Flux<User> findAllByDateOfBirthBefore(Date date);
294+
295+
Flux<User> findAllByAgeIsNull();
296+
297+
Flux<User> findAllByAgeIsNotNull();
298+
299+
Flux<User> findAllByFirstNameLike(String like);
300+
301+
Flux<User> findAllByFirstNameNotLike(String like);
250302
}
251303

252304
@Table("users")

0 commit comments

Comments
 (0)