Get started with Spring 5 and Spring Boot 2, through the reference Learn Spring course:

Authors Top

If you have a few years of experience in the Java ecosystem, and you’d like to share that with the community, have a look at our Contribution Guidelines.

Spring Top – Temp

Get started with Spring 5 and Spring Boot 2, through the reference Learn Spring course:

Lightrun – Third Party Code
announcement - icon

Flakiness in REST requests is a common issue. A request can get a 200 OK in one scenario and a 409 next time. Sometimes a request can even succeed and fail intermittently on the same exact request. In short, working over HTTP can be a bit of a mess without solid tooling.

Also, while it’s easy enough to debug these issues locally when developing the application, we’re talking about production here - we can’t afford the downtime while you’re stepping in and out of code. Uptime is kind of the whole point.

With Lightrun, you can get the same level of access you get with a local debugger or profiler - no downtime required. You can add logs, metrics, and snapshots (think breakpoints, but without stopping the running service), in a safe and read-only manner - without redeploying, restarting, or even stopping the running service. Performance and security are maintained throughout the process.

Learn how to debug a live REST API (built with Spring, of course), using Lightrun, in this 5-minute tutorial:

>> Debugging REST Requests in Spring-Based applications using the Lightrun Platform

1. Overview

In this tutorial, we'll continue with the second part of Spring Data Querydsl Web Support. Here, we'll focus on associated entities and how to create queries over HTTP.

Following the same configuration used in part one, we'll create a Maven-based project. Please refer to the original article to check how to set up the basics.

2. Entities

First, let's add a new entity (Address) creating a relationship between the user and her address. We've used the OneToOne relationship to keep it simple.

Consequently, we'll have the following classes:

public class User {

    private Long id;

    private String name;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "user") 
    private Address addresses;

    // getters & setters 
public class Address {

    private Long id;

    private String address;

    private String country;

    @OneToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "user_id") 
    private User user;

    // getters & setters

3. Spring Data Repositories

At this point, we have to create the Spring Data repositories, as usual, one for each entity. Note that these repositories will have the Querydsl configuration.

Let's see the AddressRepository repository and explain how the framework configuration works:

public interface AddressRepository extends JpaRepository<Address, Long>, 
  QuerydslPredicateExecutor<Address>, QuerydslBinderCustomizer<QAddress> {
    default void customize(QuerydslBindings bindings, QAddress root) {
          .first((SingleValueBinding<StringPath, String>) StringExpression::eq);

We’re overriding the customize() method to configure the default binding. In this case, we'll customize the default method binding to be equals, for all String properties.

Once the repository is all set, we just have to add a @RestController to manage the HTTP queries.

4. Query Rest Controller

In part one, we explained the Query@RestController over user repository, here, we'll just reuse it.

Also, we may want to query the address table; so for this, we'll just add a similar method:

@GetMapping(value = "/addresses", produces = MediaType.APPLICATION_JSON_VALUE)
public Iterable<Address> queryOverAddress(
  @QuerydslPredicate(root = Address.class) Predicate predicate) {
    BooleanBuilder builder = new BooleanBuilder();
    return addressRepository.findAll(builder.and(predicate));

Let's create some tests to see how this works.

5. Integration Testing

We've included a test to prove how Querydsl works. For this, we are using the MockMvc framework to simulate HTTP querying over user joining this entity with the new one: address. Therefore, we are now able to make queries filtering address attributes.

Let's retrieve all users living in Spain:


public void givenRequest_whenQueryUserFilteringByCountrySpain_thenGetJohn() throws Exception {
      .andExpect(jsonPath("$", hasSize(1)))
      .andExpect(jsonPath("$[0].name", is("John")))
      .andExpect(jsonPath("$[0].address.address", is("Fake Street 1")))
      .andExpect(jsonPath("$[0]", is("Spain")));

As a result, Querydsl will map the predicate sent over HTTP and generates the following SQL script:

select as id1_1_, as name2_1_ 
from user user0_ 
      cross join address address1_ 

6. Conclusion

To sum up, we have seen that Querydsl offers to the web clients a very simple alternative to create dynamic queries; another powerful use of this framework.

In part I, we saw how to retrieve data from one table; consequently, now, we can add queries joining several tables, offering web-clients a better experience filtering directly over HTTP requests they make.

The implementation of this example can be checked in the GitHub project – this is a Maven-based project, so it should be easy to import and run as it is.

Spring bottom

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

REST bottom

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course :

REST footer banner
Inline Feedbacks
View all comments
Comments are closed on this article!