Skip to content

Commit 9a59659

Browse files
committed
Add PredicateSpecification Update example.
1 parent 1dee87e commit 9a59659

File tree

3 files changed

+109
-9
lines changed

3 files changed

+109
-9
lines changed

jpa/example/src/main/java/example/springdata/jpa/simple/SimpleUserRepository.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/*
2-
* Copyright 2013-2021 the original author or authors.
2+
* Copyright 2025 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.
66
* You may obtain a copy of the License at
77
*
8-
* https://www.apache.org/licenses/LICENSE-2.0
8+
* http://www.apache.org/licenses/LICENSE-2.0
99
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,6 +24,7 @@
2424
import org.springframework.data.domain.Pageable;
2525
import org.springframework.data.domain.Slice;
2626
import org.springframework.data.domain.Sort;
27+
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
2728
import org.springframework.data.jpa.repository.Query;
2829
import org.springframework.data.repository.ListCrudRepository;
2930
import org.springframework.scheduling.annotation.Async;
@@ -36,7 +37,7 @@
3637
* @author Thomas Darimont
3738
* @author Christoph Strobl
3839
*/
39-
public interface SimpleUserRepository extends ListCrudRepository<User, Long> {
40+
public interface SimpleUserRepository extends ListCrudRepository<User, Long>, JpaSpecificationExecutor<User> {
4041

4142
/**
4243
* Find the user with the given username. This method will be translated into a query using the

jpa/example/src/test/java/example/springdata/jpa/projections/CustomerRepositoryIntegrationTest.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
import static org.assertj.core.api.Assertions.*;
1919

20+
import jakarta.persistence.EntityManager;
21+
22+
import java.util.Collection;
23+
import java.util.List;
2024
import java.util.Map;
2125

2226
import org.junit.jupiter.api.BeforeEach;
@@ -26,9 +30,11 @@
2630
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
2731
import org.springframework.boot.test.context.SpringBootTest;
2832
import org.springframework.context.annotation.Configuration;
33+
import org.springframework.data.domain.Page;
2934
import org.springframework.data.domain.PageRequest;
3035
import org.springframework.data.domain.Sort;
3136
import org.springframework.data.domain.Sort.Direction;
37+
import org.springframework.data.jpa.domain.PredicateSpecification;
3238
import org.springframework.data.projection.TargetAware;
3339
import org.springframework.transaction.annotation.Transactional;
3440

@@ -48,6 +54,7 @@ class CustomerRepositoryIntegrationTest {
4854
static class Config {}
4955

5056
@Autowired CustomerRepository customers;
57+
@Autowired EntityManager entityManager;
5158

5259
private Customer dave;
5360
private Customer carter;
@@ -96,7 +103,7 @@ void projectsDynamically() {
96103
@Test
97104
void projectsIndividualDynamically() {
98105

99-
var result = customers.findProjectedById(dave.getId(), CustomerSummary.class);
106+
CustomerSummary result = customers.findProjectedById(dave.getId(), CustomerSummary.class);
100107

101108
assertThat(result.getFullName()).isEqualTo("Dave Matthews");
102109

@@ -108,7 +115,7 @@ void projectsIndividualDynamically() {
108115
@Test
109116
void projectIndividualInstance() {
110117

111-
var projectedDave = customers.findProjectedById(dave.getId());
118+
CustomerProjection projectedDave = customers.findProjectedById(dave.getId());
112119

113120
assertThat(projectedDave.getFirstname()).isEqualTo("Dave");
114121
assertThat(projectedDave).isInstanceOfSatisfying(TargetAware.class,
@@ -118,7 +125,7 @@ void projectIndividualInstance() {
118125
@Test
119126
void projectsDtoUsingConstructorExpression() {
120127

121-
var result = customers.findDtoWithConstructorExpression("Dave");
128+
Collection<CustomerDto> result = customers.findDtoWithConstructorExpression("Dave");
122129

123130
assertThat(result).hasSize(1);
124131
assertThat(result.iterator().next().firstname()).isEqualTo("Dave");
@@ -127,7 +134,8 @@ void projectsDtoUsingConstructorExpression() {
127134
@Test
128135
void supportsProjectionInCombinationWithPagination() {
129136

130-
var page = customers.findPagedProjectedBy(PageRequest.of(0, 1, Sort.by(Direction.ASC, "lastname")));
137+
Page<CustomerProjection> page = customers
138+
.findPagedProjectedBy(PageRequest.of(0, 1, Sort.by(Direction.ASC, "lastname")));
131139

132140
assertThat(page.getContent().get(0).getFirstname()).isEqualTo("Carter");
133141
}
@@ -140,10 +148,13 @@ void appliesProjectionToOptional() {
140148
@Test
141149
void projectsWithSpecification() {
142150

143-
var result = customers.findBy((query, cb) -> cb.equal(query.get("firstname"), "Dave"),
144-
it -> it.as(CustomerDto.class).all());
151+
PredicateSpecification<Customer> isFirstName = (from, cb) -> cb.equal(from.get("firstname"), "Dave");
152+
PredicateSpecification<Customer> isLastName = (from, cb) -> cb.equal(from.get("lastname"), "Matthews");
153+
154+
List<CustomerDto> result = customers.findBy(isFirstName.and(isLastName), it -> it.as(CustomerDto.class).all());
145155

146156
assertThat(result).hasSize(1);
147157
assertThat(result).extracting(CustomerDto::firstname).containsOnly("Dave");
148158
}
159+
149160
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright 2025 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+
* http://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 example.springdata.jpa.simple;
17+
18+
import static org.assertj.core.api.Assertions.*;
19+
20+
import jakarta.persistence.EntityManager;
21+
22+
import java.util.List;
23+
24+
import org.junit.jupiter.api.BeforeEach;
25+
import org.junit.jupiter.api.Test;
26+
27+
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.boot.test.context.SpringBootTest;
29+
import org.springframework.data.jpa.domain.PredicateSpecification;
30+
import org.springframework.data.jpa.domain.UpdateSpecification;
31+
import org.springframework.transaction.annotation.Transactional;
32+
33+
/**
34+
* Integration tests for {@link SimpleUserRepository} to show specification capabilities.
35+
*
36+
* @author Mark Paluch
37+
*/
38+
@SpringBootTest
39+
@Transactional
40+
class SpecificationTests {
41+
42+
@Autowired SimpleUserRepository repository;
43+
44+
@Autowired EntityManager entityManager;
45+
46+
@BeforeEach
47+
void setUp() {
48+
49+
repository.save(new User("Dave", "Matthews"));
50+
repository.save(new User("Carter", "Beauford"));
51+
}
52+
53+
@Test
54+
void selectWithSpecification() {
55+
56+
PredicateSpecification<User> isFirstName = (from, cb) -> cb.equal(from.get("firstname"), "Dave");
57+
PredicateSpecification<User> isLastName = (from, cb) -> cb.equal(from.get("lastname"), "Matthews");
58+
59+
List<User> result = repository.findAll(isFirstName.and(isLastName));
60+
61+
assertThat(result).hasSize(1);
62+
assertThat(result).extracting(User::getFirstname).containsOnly("Dave");
63+
}
64+
65+
@Test
66+
void updateWithSpecification() {
67+
68+
PredicateSpecification<User> isFirstName = (from, cb) -> cb.equal(from.get("firstname"), "Dave");
69+
PredicateSpecification<User> isLastName = (from, cb) -> cb.equal(from.get("lastname"), "Matthews");
70+
71+
UpdateSpecification<User> specification = UpdateSpecification.<User> update((root, update, criteriaBuilder) -> {
72+
update.set("firstname", "Dan");
73+
update.set("lastname", "Brown");
74+
}).where(isFirstName.and(isLastName));
75+
76+
assertThat(repository.update(specification)).isEqualTo(1);
77+
entityManager.clear();
78+
79+
assertThat(repository.findAll(isFirstName)).isEmpty();
80+
81+
List<User> result = repository.findAll((from, cb) -> cb.equal(from.get("firstname"), "Dan"));
82+
83+
assertThat(result).hasSize(1);
84+
assertThat(result).extracting(User::getFirstname).containsOnly("Dan");
85+
assertThat(result).extracting(User::getLastname).containsOnly("Brown");
86+
}
87+
88+
}

0 commit comments

Comments
 (0)