Skip to content

Commit fc1f167

Browse files
Merge branch 'main' into feat/2409_intro_JSQLParses
2 parents 7045f4c + 037ea9c commit fc1f167

File tree

11 files changed

+225
-31
lines changed

11 files changed

+225
-31
lines changed

Jenkinsfile

+19-13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
def p = [:]
2+
node {
3+
checkout scm
4+
p = readProperties interpolate: true, file: 'ci/pipeline.properties'
5+
}
6+
17
pipeline {
28
agent none
39

@@ -25,13 +31,13 @@ pipeline {
2531
}
2632
options { timeout(time: 30, unit: 'MINUTES') }
2733
environment {
28-
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
29-
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
34+
DOCKER_HUB = credentials("${p['docker.credentials']}")
35+
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
3036
}
3137
steps {
3238
script {
33-
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
34-
docker.image('adoptopenjdk/openjdk8:latest').inside('-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home') {
39+
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
40+
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) {
3541
sh "docker login --username ${DOCKER_HUB_USR} --password ${DOCKER_HUB_PSW}"
3642
sh 'PROFILE=all-dbs ci/test.sh'
3743
sh "ci/clean.sh"
@@ -56,12 +62,12 @@ pipeline {
5662
}
5763
options { timeout(time: 30, unit: 'MINUTES') }
5864
environment {
59-
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
65+
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
6066
}
6167
steps {
6268
script {
63-
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
64-
docker.image('adoptopenjdk/openjdk11:latest').inside('-v $HOME:/tmp/jenkins-home') {
69+
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
70+
docker.image(p['docker.java.next.image']).inside(p['docker.java.inside.basic']) {
6571
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pjava11 clean dependency:list test -Dsort -Dbundlor.enabled=false -U -B'
6672
}
6773
}
@@ -75,12 +81,12 @@ pipeline {
7581
}
7682
options { timeout(time: 30, unit: 'MINUTES') }
7783
environment {
78-
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
84+
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
7985
}
8086
steps {
8187
script {
82-
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
83-
docker.image('openjdk:17-bullseye').inside('-v $HOME:/tmp/jenkins-home') {
88+
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
89+
docker.image(p['docker.java.lts.image']).inside(p['docker.java.inside.basic']) {
8490
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pjava11 clean dependency:list test -Dsort -Dbundlor.enabled=false -U -B'
8591
}
8692
}
@@ -104,13 +110,13 @@ pipeline {
104110
options { timeout(time: 20, unit: 'MINUTES') }
105111

106112
environment {
107-
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
113+
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
108114
}
109115

110116
steps {
111117
script {
112-
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
113-
docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') {
118+
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
119+
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.basic']) {
114120
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,artifactory ' +
115121
'-Dartifactory.server=https://repo.spring.io ' +
116122
"-Dartifactory.username=${ARTIFACTORY_USR} " +

ci/pipeline.properties

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Java versions
2+
java.main.tag=8u312-b07-jdk
3+
java.next.tag=11.0.13_8-jdk
4+
java.lts.tag=17.0.1_12-jdk
5+
6+
# Docker container images - standard
7+
docker.java.main.image=eclipse-temurin:${java.main.tag}
8+
docker.java.next.image=eclipse-temurin:${java.next.tag}
9+
docker.java.lts.image=eclipse-temurin:${java.lts.tag}
10+
11+
# Supported versions of MongoDB
12+
docker.mongodb.4.0.version=4.0.23
13+
docker.mongodb.4.4.version=4.4.4
14+
docker.mongodb.5.0.version=5.0.3
15+
16+
# Supported versions of Redis
17+
docker.redis.6.version=6.2.4
18+
19+
# Supported versions of Cassandra
20+
docker.cassandra.3.version=3.11.10
21+
22+
# Docker environment settings
23+
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home
24+
docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home
25+
26+
# Credentials
27+
docker.registry=
28+
docker.credentials=hub.docker.com-springbuildmaster
29+
artifactory.credentials=02bd1690-b54f-4c9f-819d-a77cb7a9822c

src/main/java/org/springframework/data/jpa/convert/QueryByExamplePredicateBuilder.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2021 the original author or authors.
2+
* Copyright 2016-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -56,6 +56,7 @@
5656
* @author Mark Paluch
5757
* @author Oliver Gierke
5858
* @author Jens Schauder
59+
* @author Greg Turnquist
5960
* @since 1.10
6061
*/
6162
public class QueryByExamplePredicateBuilder {
@@ -146,6 +147,10 @@ static List<Predicate> getPredicates(String path, CriteriaBuilder cb, Path<?> fr
146147

147148
Object attributeValue = optionalValue.get();
148149

150+
if (attributeValue == Optional.empty()) {
151+
continue;
152+
}
153+
149154
if (attribute.getPersistentAttributeType().equals(PersistentAttributeType.EMBEDDED)
150155
|| (isAssociation(attribute) && !(from instanceof From))) {
151156

@@ -273,7 +278,7 @@ public String toString() {
273278

274279
StringBuilder sb = new StringBuilder();
275280
if (parent != null) {
276-
sb.append(parent.toString());
281+
sb.append(parent);
277282
sb.append(" -");
278283
sb.append(name);
279284
sb.append("-> ");

src/main/java/org/springframework/data/jpa/repository/config/BeanDefinitionNames.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2021 the original author or authors.
2+
* Copyright 2014-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
2424
*/
2525
interface BeanDefinitionNames {
2626

27-
public static final String JPA_MAPPING_CONTEXT_BEAN_NAME = "jpaMappingContext";
28-
public static final String JPA_CONTEXT_BEAN_NAME = "jpaContext";
29-
public static final String EM_BEAN_DEFINITION_REGISTRAR_POST_PROCESSOR_BEAN_NAME = "emBeanDefinitionRegistrarPostProcessor";
27+
String JPA_MAPPING_CONTEXT_BEAN_NAME = "jpaMappingContext";
28+
String JPA_CONTEXT_BEAN_NAME = "jpaContext";
29+
String EM_BEAN_DEFINITION_REGISTRAR_POST_PROCESSOR_BEAN_NAME = "emBeanDefinitionRegistrarPostProcessor";
3030
}

src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public abstract class AbstractJpaQuery implements RepositoryQuery {
6969
private final PersistenceProvider provider;
7070
private final Lazy<JpaQueryExecution> execution;
7171

72-
final Lazy<ParameterBinder> parameterBinder = new Lazy<>(this::createBinder);
72+
final Lazy<ParameterBinder> parameterBinder = Lazy.of(this::createBinder);
7373

7474
/**
7575
* Creates a new {@link AbstractJpaQuery} from the given {@link JpaQueryMethod}.

src/main/java/org/springframework/data/jpa/repository/query/StringQuery.java

+9-9
Original file line numberDiff line numberDiff line change
@@ -764,15 +764,15 @@ public Object prepare(@Nullable Object value) {
764764
}
765765

766766
switch (type) {
767-
case STARTING_WITH:
768-
return String.format("%s%%", value.toString());
769-
case ENDING_WITH:
770-
return String.format("%%%s", value.toString());
771-
case CONTAINING:
772-
return String.format("%%%s%%", value.toString());
773-
case LIKE:
774-
default:
775-
return value;
767+
case STARTING_WITH:
768+
return String.format("%s%%", value);
769+
case ENDING_WITH:
770+
return String.format("%%%s", value);
771+
case CONTAINING:
772+
return String.format("%%%s%%", value);
773+
case LIKE:
774+
default:
775+
return value;
776776
}
777777
}
778778

src/main/java/org/springframework/data/jpa/support/ClasspathScanningPersistenceUnitPostProcessor.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2021 the original author or authors.
2+
* Copyright 2011-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -191,7 +191,7 @@ private Set<String> scanForMappingFileLocations() {
191191
mappingFileUris.add(resourcePathInClasspath);
192192

193193
} catch (IOException e) {
194-
throw new IllegalStateException(String.format("Couldn't get URI for %s!", resource.toString()), e);
194+
throw new IllegalStateException(String.format("Couldn't get URI for %s!", resource), e);
195195
}
196196
}
197197

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright 2008-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.jpa.domain.sample;
17+
18+
import lombok.Data;
19+
20+
import java.util.Optional;
21+
22+
import javax.persistence.Entity;
23+
import javax.persistence.GeneratedValue;
24+
import javax.persistence.Id;
25+
26+
import org.springframework.lang.Nullable;
27+
28+
/**
29+
* @author Greg Turnquist
30+
*/
31+
@Entity
32+
@Data
33+
public class UserWithOptionalField {
34+
35+
@Id @GeneratedValue private Long id;
36+
private String name;
37+
private String role;
38+
39+
public UserWithOptionalField() {
40+
41+
this.id = null;
42+
this.name = null;
43+
this.role = null;
44+
}
45+
46+
public UserWithOptionalField(String name, @Nullable String role) {
47+
48+
this();
49+
this.name = name;
50+
this.role = role;
51+
}
52+
53+
public Optional<String> getRole() {
54+
return Optional.ofNullable(this.role);
55+
}
56+
57+
public void setRole(Optional<String> role) {
58+
this.role = role.orElse(null);
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2008-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.jpa.domain.sample;
17+
18+
import org.springframework.data.jpa.repository.JpaRepository;
19+
20+
/**
21+
* @author Greg Turnquist
22+
*/
23+
public interface UserWithOptionalFieldRepository extends JpaRepository<UserWithOptionalField, Long> {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2008-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.jpa.domain.support;
17+
18+
import static org.assertj.core.api.Assertions.*;
19+
20+
import java.util.List;
21+
import java.util.Optional;
22+
23+
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.extension.ExtendWith;
25+
import org.springframework.beans.factory.annotation.Autowired;
26+
import org.springframework.context.annotation.Configuration;
27+
import org.springframework.context.annotation.ImportResource;
28+
import org.springframework.data.domain.Example;
29+
import org.springframework.data.jpa.domain.sample.UserWithOptionalField;
30+
import org.springframework.data.jpa.domain.sample.UserWithOptionalFieldRepository;
31+
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
32+
import org.springframework.test.context.ContextConfiguration;
33+
import org.springframework.test.context.junit.jupiter.SpringExtension;
34+
35+
/**
36+
* Integration test for {@link org.springframework.data.repository.query.QueryByExampleExecutor} involving
37+
* {@link Optional#empty()}.
38+
*
39+
* @author Greg Turnquist
40+
*/
41+
@ExtendWith(SpringExtension.class)
42+
@ContextConfiguration
43+
public class QueryByExampleWithOptionalEmptyTests {
44+
45+
@Autowired UserWithOptionalFieldRepository repository;
46+
UserWithOptionalField user;
47+
48+
@Test
49+
void queryByExampleTreatsEmptyOptionalsLikeNulls() {
50+
51+
UserWithOptionalField user = new UserWithOptionalField();
52+
user.setName("Greg");
53+
repository.saveAndFlush(user);
54+
55+
UserWithOptionalField probe = new UserWithOptionalField();
56+
probe.setName("Greg");
57+
Example<UserWithOptionalField> example = Example.of(probe);
58+
59+
List<UserWithOptionalField> results = repository.findAll(example);
60+
61+
assertThat(results).hasSize(1);
62+
assertThat(results).extracting(UserWithOptionalField::getName).containsExactly("Greg");
63+
}
64+
65+
@Configuration
66+
@EnableJpaRepositories(basePackageClasses = UserWithOptionalFieldRepository.class)
67+
@ImportResource("classpath:infrastructure.xml")
68+
static class JpaRepositoryConfig {}
69+
70+
}

src/test/resources/META-INF/persistence.xml

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
<class>org.springframework.data.jpa.domain.sample.Site</class>
4646
<class>org.springframework.data.jpa.domain.sample.SpecialUser</class>
4747
<class>org.springframework.data.jpa.domain.sample.User</class>
48+
<class>org.springframework.data.jpa.domain.sample.UserWithOptionalField</class>
4849
<class>org.springframework.data.jpa.domain.sample.VersionedUser</class>
4950
<class>org.springframework.data.jpa.domain.sample.Dummy</class>
5051
<class>org.springframework.data.jpa.domain.sample.SampleWithIdClassIncludingEntity</class>

0 commit comments

Comments
 (0)