Spring - QueryDSL

Overview

Spring Boot QueryDSL lets you query the database using domain specific language similar to SQL.

Github: https://github.com/gitorko/project75

Spring QueryDSL

Let's say you used Spring Data to query the db by using spring naming convention. If your table has 100's of column and you have to query by any column you can't write 100 access functions. This is where query dsl comes into play.

Code

  1package com.demo.project75;
  2
  3import java.util.stream.IntStream;
  4import javax.persistence.Entity;
  5import javax.persistence.GeneratedValue;
  6import javax.persistence.GenerationType;
  7import javax.persistence.Id;
  8
  9import com.querydsl.core.types.dsl.StringExpression;
 10import com.querydsl.core.types.dsl.StringPath;
 11import lombok.AllArgsConstructor;
 12import lombok.Builder;
 13import lombok.Data;
 14import lombok.NoArgsConstructor;
 15import org.springframework.beans.factory.annotation.Autowired;
 16import org.springframework.boot.SpringApplication;
 17import org.springframework.boot.autoconfigure.SpringBootApplication;
 18import org.springframework.context.event.ContextRefreshedEvent;
 19import org.springframework.context.event.EventListener;
 20import org.springframework.data.jpa.repository.JpaRepository;
 21import org.springframework.data.querydsl.QuerydslPredicateExecutor;
 22import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
 23import org.springframework.data.querydsl.binding.QuerydslBindings;
 24import org.springframework.data.querydsl.binding.QuerydslPredicate;
 25import org.springframework.data.querydsl.binding.SingleValueBinding;
 26import org.springframework.web.bind.annotation.RequestMapping;
 27import org.springframework.web.bind.annotation.RequestMethod;
 28import org.springframework.web.bind.annotation.RestController;
 29
 30@SpringBootApplication
 31public class Main {
 32
 33    @Autowired
 34    CustomerRepository customerRepository;
 35
 36    public static void main(String[] args) {
 37        SpringApplication.run(Main.class, args);
 38    }
 39
 40    @EventListener
 41    public void onStartSeedData(ContextRefreshedEvent event) {
 42        //Insert test data
 43        IntStream.range(0,5).forEach(i -> {
 44            customerRepository.save(Customer.builder()
 45                    .firstName("firstname_" + i)
 46                    .lastName("lastname " + i)
 47                    .age(30)
 48                    .email("email@email.com")
 49                    .build());
 50        });
 51    }
 52}
 53
 54@Entity
 55@Data
 56@AllArgsConstructor
 57@NoArgsConstructor
 58@Builder
 59class Customer {
 60    @Id
 61    @GeneratedValue(strategy = GenerationType.AUTO)
 62    private Long id;
 63    private String firstName;
 64    private String lastName;
 65    private String email;
 66    private int age;
 67}
 68
 69@RestController
 70class HomeController{
 71
 72    @Autowired
 73    CustomerRepository customerRepository;
 74
 75    @RequestMapping(method = RequestMethod.GET, value = "/users")
 76    public Iterable<Customer> findAllByWebQuerydsl(
 77            @QuerydslPredicate(root = Customer.class,
 78                                bindings = CustomerBinderCustomizer.class) com.querydsl.core.types.Predicate predicate) {
 79        return customerRepository.findAll(predicate);
 80    }
 81}
 82
 83interface CustomerRepository extends JpaRepository<Customer, Long>, QuerydslPredicateExecutor<Customer> {
 84}
 85
 86class CustomerBinderCustomizer implements QuerydslBinderCustomizer<QCustomer> {
 87
 88    @Override
 89    public void customize(QuerydslBindings querydslBindings, QCustomer qCustomer) {
 90        querydslBindings.including(
 91                        qCustomer.id,
 92                        qCustomer.firstName,
 93                        qCustomer.lastName,
 94                        qCustomer.age,
 95                        qCustomer.email);
 96
 97        // Allow case-insensitive partial searches on all strings.
 98        querydslBindings.bind(String.class).first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
 99    }
100}

It uses in memory h2 db to persist.

Setup

Project 75

Spring Boot - Querydsl

https://gitorko.github.io/spring-boot-querydsl/

Version

Check version

1$java --version
2openjdk 17.0.3 2022-04-19 LTS

Dev

To run the code.

1./gradlew clean build
2./gradlew bootRun

Testing

You can now search based on all the columns of the db and get the response.

http://localhost:8080/users?age=30

http://localhost:8080/users?firstName=firstname_0

http://localhost:8080/users?firstName=firstname_0&age=30

References

Spring Query DSL : http://www.querydsl.com/static/querydsl/latest/reference/html/ch02.html

comments powered by Disqus