Skip to content

Commit 94c77ea

Browse files
committed
Added sample for QueryDsl integration.
1 parent c9356b1 commit 94c77ea

File tree

11 files changed

+188
-78
lines changed

11 files changed

+188
-78
lines changed

spring-data-jpa-showcase/demo.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,21 @@
3434
- implementation got obsolete
3535
- switch to after package
3636

37+
7. Querydsl / Specifications
38+
----------------------------
39+
- Introduce Querydsl
40+
- Show Maven setup
41+
- Show predicates
42+
- Integrate test case
43+
3744
7. Custom implementation
3845
------------------------
3946
- copy interface and implementation (hint to visibility)
4047
- adapt AccountRepository
4148
- copy test case
4249
- explain implementation class lookup
4350

44-
8. JDBC implementation
51+
8. JDBC implementation (optional)
4552
-----------------------
4653
- copy implementation -> configuration necessary
4754
- copy XML

spring-data-jpa-showcase/pom.xml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313

1414
<name>Spring Data JPA showcase</name>
1515
<description>Sample project showing how Spring Data JPA eases implementing repositories over a plain JPA/Spring approach</description>
16+
17+
<properties>
18+
<querydsl.version>2.1.1</querydsl.version>
19+
</properties>
1620

1721
<build>
1822

@@ -71,5 +75,59 @@
7175
</plugin>
7276
</plugins>
7377
</build>
78+
79+
<profiles>
80+
<profile>
81+
<id>querydsl</id>
82+
<activation>
83+
<activeByDefault>true</activeByDefault>
84+
</activation>
85+
<dependencies>
86+
<!-- QueryDsl -->
87+
<dependency>
88+
<groupId>com.mysema.querydsl</groupId>
89+
<artifactId>querydsl-apt</artifactId>
90+
<version>${querydsl.version}</version>
91+
<scope>provided</scope>
92+
</dependency>
93+
94+
<dependency>
95+
<groupId>com.mysema.querydsl</groupId>
96+
<artifactId>querydsl-jpa</artifactId>
97+
<version>${querydsl.version}</version>
98+
</dependency>
99+
</dependencies>
100+
101+
<repositories>
102+
<repository>
103+
<id>querydsl</id>
104+
<name>QueryDsl</name>
105+
<url>http://source.mysema.com/maven2/releases</url>
106+
</repository>
107+
</repositories>
108+
109+
<build>
110+
<plugins>
111+
<plugin>
112+
<groupId>com.mysema.maven</groupId>
113+
<artifactId>maven-apt-plugin</artifactId>
114+
<version>1.0</version>
115+
<executions>
116+
<execution>
117+
<phase>generate-sources</phase>
118+
<goals>
119+
<goal>process</goal>
120+
</goals>
121+
<configuration>
122+
<outputDirectory>target/generated-sources/queries</outputDirectory>
123+
<processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
124+
</configuration>
125+
</execution>
126+
</executions>
127+
</plugin>
128+
</plugins>
129+
</build>
130+
</profile>
131+
</profiles>
74132

75133
</project>

spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/after/AccountRepository.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
*/
1414
public interface AccountRepository extends CrudRepository<Account, Long> {
1515

16-
/**
17-
* Returns all accounts belonging to the given {@link Customer}.
18-
*
19-
* @param customer
20-
* @return
21-
*/
22-
List<Account> findByCustomer(Customer customer);
16+
/**
17+
* Returns all accounts belonging to the given {@link Customer}.
18+
*
19+
* @param customer
20+
* @return
21+
*/
22+
List<Account> findByCustomer(Customer customer);
2323
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.springframework.data.jpa.showcase.snippets;
2+
3+
import org.joda.time.LocalDate;
4+
import org.springframework.data.jpa.showcase.core.Account;
5+
import org.springframework.data.jpa.showcase.core.QAccount;
6+
7+
import com.mysema.query.types.expr.BooleanExpression;
8+
9+
/**
10+
* Predicates for {@link Account}s.
11+
*
12+
* @author Oliver Gierke
13+
*/
14+
public class AccountPredicates {
15+
16+
private static QAccount $ = QAccount.account;
17+
18+
public static BooleanExpression isExpired() {
19+
return expiresBefore(new LocalDate());
20+
}
21+
22+
public static BooleanExpression expiresBefore(LocalDate date) {
23+
return $.expiryDate.before(date.toDateMidnight().toDate());
24+
}
25+
}

spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepository.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,22 @@
44

55
import org.springframework.data.jpa.showcase.core.Account;
66
import org.springframework.data.jpa.showcase.core.Customer;
7+
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
78
import org.springframework.data.repository.CrudRepository;
89

9-
1010
/**
1111
* Repository to manage {@link Account} instances.
1212
*
1313
* @author Oliver Gierke
1414
*/
15-
public interface AccountRepository extends CrudRepository<Account, Long>, AccountRepositoryCustom {
15+
public interface AccountRepository extends CrudRepository<Account, Long>, AccountRepositoryCustom,
16+
QueryDslPredicateExecutor<Account> {
1617

17-
/**
18-
* Returns all accounts belonging to the given {@link Customer}.
19-
*
20-
* @param customer
21-
* @return
22-
*/
23-
List<Account> findByCustomer(Customer customer);
18+
/**
19+
* Returns all accounts belonging to the given {@link Customer}.
20+
*
21+
* @param customer
22+
* @return
23+
*/
24+
List<Account> findByCustomer(Customer customer);
2425
}

spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/CustomerSpecifications.java

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,33 @@
1313
import org.springframework.data.jpa.showcase.core.Account;
1414
import org.springframework.data.jpa.showcase.core.Customer;
1515

16-
1716
/**
1817
* Collection of {@link Specification} implementations.
1918
*
2019
* @author Oliver Gierke
2120
*/
2221
public class CustomerSpecifications {
2322

24-
/**
25-
* All customers with an {@link Account} expiring before the given date.
26-
*
27-
* @param date
28-
* @return
29-
*/
30-
public static Specification<Customer> accountExpiresBefore(
31-
final LocalDate date) {
32-
33-
return new Specification<Customer>() {
34-
35-
@Override
36-
public Predicate toPredicate(Root<Customer> root,
37-
CriteriaQuery<?> query, CriteriaBuilder cb) {
38-
39-
Root<Account> accounts = query.from(Account.class);
40-
Path<Date> expiryDate = accounts.<Date> get("expiryDate");
41-
Predicate customerIsAccountOwner =
42-
cb.equal(accounts.<Customer> get("customer"), root);
43-
Predicate accountExpiryDateBefore =
44-
cb.lessThan(expiryDate, date.toDateMidnight().toDate());
45-
46-
return cb.and(customerIsAccountOwner, accountExpiryDateBefore);
47-
}
48-
};
49-
}
23+
/**
24+
* All customers with an {@link Account} expiring before the given date.
25+
*
26+
* @param date
27+
* @return
28+
*/
29+
public static Specification<Customer> accountExpiresBefore(final LocalDate date) {
30+
31+
return new Specification<Customer>() {
32+
33+
@Override
34+
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
35+
36+
Root<Account> accounts = query.from(Account.class);
37+
Path<Date> expiryDate = accounts.<Date> get("expiryDate");
38+
Predicate customerIsAccountOwner = cb.equal(accounts.<Customer> get("customer"), root);
39+
Predicate accountExpiryDateBefore = cb.lessThan(expiryDate, date.toDateMidnight().toDate());
40+
41+
return cb.and(customerIsAccountOwner, accountExpiryDateBefore);
42+
}
43+
};
44+
}
5045
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
11
package org.springframework.data.jpa.showcase.snippets.test;
22

3-
import static org.hamcrest.CoreMatchers.*;
3+
import static org.hamcrest.Matchers.*;
44
import static org.junit.Assert.*;
5+
import static org.springframework.data.jpa.showcase.snippets.AccountPredicates.*;
56

67
import org.joda.time.LocalDate;
8+
import org.springframework.data.jpa.showcase.core.Account;
79
import org.springframework.data.jpa.showcase.snippets.AccountRepository;
810

9-
1011
/**
1112
* @author Oliver Gierke
1213
*/
1314
public abstract class AccountRepositoryIntegrationTest {
1415

15-
private AccountRepository accountRepository;
16+
private AccountRepository accountRepository;
17+
18+
public void removesExpiredAccountsCorrectly() throws Exception {
19+
20+
accountRepository.removedExpiredAccounts(new LocalDate(2011, 1, 1));
21+
assertThat(accountRepository.count(), is(1L));
22+
}
23+
24+
public void findsExpiredAccounts() {
1625

26+
Account expired = accountRepository.findOne(1L);
27+
Account valid = accountRepository.findOne(2L);
1728

18-
public void removesExpiredAccountsCorrectly() throws Exception {
29+
Iterable<Account> findAll = accountRepository.findAll(expiresBefore(new LocalDate(2011, 3, 1)));
1930

20-
accountRepository.removedExpiredAccounts(new LocalDate(2011, 1, 1));
21-
assertThat(accountRepository.count(), is(1L));
22-
}
31+
assertThat(findAll, hasItem(expired));
32+
assertThat(findAll, not(hasItem(valid)));
33+
}
2334
}

spring-data-jpa-showcase/src/test-snippets/java/org/springframework/data/jpa/showcase/snippets/test/CustomerRepositoryIntegrationTest.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,23 @@
1212
import org.springframework.data.jpa.showcase.after.CustomerRepository;
1313
import org.springframework.data.jpa.showcase.core.Customer;
1414

15-
1615
/**
1716
* Snippets to show the usage of {@link Specification}s.
1817
*
1918
* @author Oliver Gierke
2019
*/
2120
public class CustomerRepositoryIntegrationTest {
2221

23-
CustomerRepository repository;
24-
22+
CustomerRepository repository;
2523

26-
public void findsCustomersBySpecification() throws Exception {
24+
public void findsCustomersBySpecification() throws Exception {
2725

28-
Customer dave = repository.findOne(1L);
26+
Customer dave = repository.findOne(1L);
2927

30-
LocalDate expiryLimit = new LocalDate(2011, 3, 1);
31-
List<Customer> result =
32-
repository.findAll(where(accountExpiresBefore(expiryLimit)));
28+
LocalDate expiryLimit = new LocalDate(2011, 3, 1);
29+
List<Customer> result = repository.findAll(where(accountExpiresBefore(expiryLimit)));
3330

34-
assertThat(result.size(), is(1));
35-
assertThat(result, hasItems(dave));
36-
}
31+
assertThat(result.size(), is(1));
32+
assertThat(result, hasItems(dave));
33+
}
3734
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package org.springframework.data.jpa.showcase.after;
22

3-
import static org.hamcrest.CoreMatchers.*;
3+
import static org.hamcrest.Matchers.*;
44
import static org.junit.Assert.*;
55

66
import java.util.List;
@@ -12,27 +12,25 @@
1212
import org.springframework.data.jpa.showcase.core.Customer;
1313
import org.springframework.test.context.ContextConfiguration;
1414

15-
1615
/**
1716
* @author Oliver Gierke
1817
*/
1918
@ContextConfiguration("classpath:application-context-after.xml")
2019
public class AccountRepositoryIntegrationTest extends AbstractShowcaseTest {
2120

22-
@Autowired
23-
AccountRepository accountRepository;
24-
25-
@Autowired
26-
CustomerRepository customerRepository;
21+
@Autowired
22+
AccountRepository accountRepository;
2723

24+
@Autowired
25+
CustomerRepository customerRepository;
2826

29-
@Test
30-
public void findsCustomersAccounts() throws Exception {
27+
@Test
28+
public void findsCustomersAccounts() {
3129

32-
Customer customer = customerRepository.findOne(1L);
33-
List<Account> accounts = accountRepository.findByCustomer(customer);
30+
Customer customer = customerRepository.findOne(1L);
31+
List<Account> accounts = accountRepository.findByCustomer(customer);
3432

35-
assertFalse(accounts.isEmpty());
36-
assertThat(accounts.get(0).getCustomer(), is(customer));
37-
}
33+
assertFalse(accounts.isEmpty());
34+
assertThat(accounts.get(0).getCustomer(), is(customer));
35+
}
3836
}

spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/after/CustomerRepositoryIntegrationTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22

33
import static org.hamcrest.Matchers.*;
44
import static org.junit.Assert.*;
5+
import static org.springframework.data.jpa.domain.Specifications.*;
6+
import static org.springframework.data.jpa.showcase.snippets.CustomerSpecifications.*;
57

8+
import java.util.List;
9+
10+
import org.joda.time.LocalDate;
611
import org.junit.Test;
712
import org.springframework.beans.factory.annotation.Autowired;
813
import org.springframework.data.domain.Page;
@@ -46,4 +51,16 @@ public void findsCustomerById() throws Exception {
4651
assertThat(customer.getFirstname(), is("Carter"));
4752
assertThat(customer.getLastname(), is("Beauford"));
4853
}
54+
55+
@Test
56+
public void findsCustomersBySpecification() throws Exception {
57+
58+
Customer dave = repository.findOne(1L);
59+
60+
LocalDate expiryLimit = new LocalDate(2011, 3, 1);
61+
List<Customer> result = repository.findAll(where(accountExpiresBefore(expiryLimit)));
62+
63+
assertThat(result.size(), is(1));
64+
assertThat(result, hasItems(dave));
65+
}
4966
}

spring-data-jpa-showcase/template.mf

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ Import-Package:
99
org.hsqldb;version="[1.8.0,1.9.0)"
1010
Export-Template:
1111
org.springframework.data.jpa.sample.*;version="${project.version}"
12-
Import-Template:
13-
javax.persistence.*;version="${jpa.version:[=.=.=,+1.0.0)}",
12+
Import-Template:
13+
com.mysema.query.*;version="${querydsl.version:[2.1.1,+1.0.0)}",
14+
javax.persistence.*;version="${jpa.version:[=.=.=,+1.0.0)}",
1415
org.springframework.*;version="${spring.version:[=.=.=.=,+1.0.0)}",
1516
org.springframework.data.*;version="${project.version:[=.=.=.=,+1.0.0)}",
1617
org.joda.time.*;version="${jodatime.version:[=.=.=,+1.0.0]}"

0 commit comments

Comments
 (0)