Skip to content

Commit

Permalink
added query dsl and web support
Browse files Browse the repository at this point in the history
  • Loading branch information
Undersent committed Nov 5, 2017
1 parent 60a30b5 commit 0dbaa86
Show file tree
Hide file tree
Showing 9 changed files with 412 additions and 12 deletions.
99 changes: 92 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<packaging>jar</packaging>

<name>demo</name>
<description></description>


<parent>
<groupId>org.springframework.boot</groupId>
Expand All @@ -22,9 +22,39 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<querydsl.version>4.1.3</querydsl.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
<!-- Querydsl -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
</dependency>


<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
Expand All @@ -39,10 +69,7 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>


<dependency>
<groupId>mysql</groupId>
Expand All @@ -63,13 +90,71 @@
<artifactId>google-collections</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured.examples</groupId>
<artifactId>scala-example</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>


</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>

<!--<groupId>com.mysema.maven</groupId>-->
<!--<artifactId>apt-maven-plugin</artifactId>-->
<!--<version>1.1.3</version>-->
<!--<dependencies>-->
<!--<dependency>-->
<!--<groupId>com.mysema.querydsl</groupId>-->
<!--<artifactId>querydsl-apt</artifactId>-->
<!--<version>${querydsl.version}</version>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>org.mapstruct</groupId>-->
<!--<artifactId>mapstruct-processor</artifactId>-->
<!--<version>1.2.0.Final</version>-->
<!--</dependency>-->
<!--</dependencies>-->
<!--<executions>-->
<!--<execution>-->
<!--<phase>generate-sources</phase>-->
<!--<goals>-->
<!--<goal>process</goal>-->
<!--</goals>-->
<!--<configuration>-->
<!--<outputDirectory>${project.build.directory}/generated-sources</outputDirectory>-->
<!--<processors>-->
<!--<processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>-->
<!--<processor>org.mapstruct.ap.MappingProcessor</processor>-->
<!--</processors>-->
<!--</configuration>-->
<!--</execution>-->
<!--</executions>-->
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.example.demo.persistence.dao;

import com.example.demo.persistence.model.MyUser;
import com.example.demo.web.util.SearchCriteria;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.NumberPath;
import com.querydsl.core.types.dsl.PathBuilder;
import com.querydsl.core.types.dsl.StringPath;

public class MyUserPredicate {

private SearchCriteria criteria;

public MyUserPredicate(final SearchCriteria criteria) {
this.criteria = criteria;
}

public BooleanExpression getPredicate() {
final PathBuilder<MyUser> entityPath = new PathBuilder<>(MyUser.class, "myUser");

if (isNumeric(criteria.getValue().toString())) {
final NumberPath<Integer> path = entityPath.getNumber(criteria.getKey(), Integer.class);
final int value = Integer.parseInt(criteria.getValue().toString());
switch (criteria.getOperation()) {
case ":":
return path.eq(value);
case ">":
return path.goe(value);
case "<":
return path.loe(value);
}
} else {
final StringPath path = entityPath.getString(criteria.getKey());
if (criteria.getOperation().equalsIgnoreCase(":")) {
return path.containsIgnoreCase(criteria.getValue().toString());
}
}
return null;
}

public SearchCriteria getCriteria() {
return criteria;
}

public void setCriteria(final SearchCriteria criteria) {
this.criteria = criteria;
}

public static boolean isNumeric(final String str) {
try {
Integer.parseInt(str);
} catch (final NumberFormatException e) {
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.example.demo.persistence.dao;

import com.example.demo.web.util.SearchCriteria;
import com.querydsl.core.types.dsl.BooleanExpression;

import java.util.ArrayList;
import java.util.List;

public final class MyUserPredicateBuilder {
private final List<SearchCriteria> params;

public MyUserPredicateBuilder() {
params = new ArrayList<>();
}

public MyUserPredicateBuilder with(final String key, final String operation, final Object value) {
params.add(new SearchCriteria(key, operation, value));
return this;
}

public BooleanExpression build() {
if (params.size() == 0) {
return null;
}

final List<BooleanExpression> predicates = new ArrayList<>();
MyUserPredicate predicate;
for (final SearchCriteria param : params) {
predicate = new MyUserPredicate(param);
final BooleanExpression exp = predicate.getPredicate();
if (exp != null) {
predicates.add(exp);
}
}

BooleanExpression result = predicates.get(0);
for (int i = 1; i < predicates.size(); i++) {
result = result.and(predicates.get(i));
}
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.example.demo.persistence.dao.repository;

import com.example.demo.persistence.model.MyUser;
import com.example.demo.persistence.model.QMyUser;
import com.querydsl.core.types.dsl.StringExpression;
import com.querydsl.core.types.dsl.StringPath;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
import org.springframework.data.querydsl.binding.QuerydslBindings;
import com.querydsl.core.types.dsl.StringExpression;

import com.querydsl.core.types.dsl.StringPath;
import org.springframework.data.querydsl.binding.SingleValueBinding;

public interface MyUserRepository extends JpaRepository<MyUser, Long>,
QueryDslPredicateExecutor<MyUser>, QuerydslBinderCustomizer<QMyUser> {

@Override
default void customize(final QuerydslBindings bindings, final QMyUser root) {
bindings.bind(String.class)
.first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
bindings.excluding(root.email);
}
}

31 changes: 31 additions & 0 deletions src/main/java/com/example/demo/persistence/model/MyUser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.example.demo.persistence.model;

import lombok.*;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@Setter
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class MyUser {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;

private String firstName;

private String lastName;

private String email;

private int age;
}
2 changes: 2 additions & 0 deletions src/main/java/com/example/demo/persistence/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Expand Down
38 changes: 33 additions & 5 deletions src/main/java/com/example/demo/web/controller/UserController.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package com.example.demo.web.controller;

import com.example.demo.persistence.dao.IUserDao;
import com.example.demo.persistence.dao.MyUserPredicateBuilder;
import com.example.demo.persistence.dao.UserSpecificationBuilder;
import com.example.demo.persistence.dao.repository.MyUserRepository;
import com.example.demo.persistence.dao.repository.UserRepository;
import com.example.demo.persistence.model.MyUser;
import com.example.demo.persistence.model.User;
import com.example.demo.web.util.SearchCriteria;
import com.querydsl.core.types.dsl.BooleanExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.data.querydsl.binding.QuerydslPredicate;
import org.springframework.web.bind.annotation.*;
import com.querydsl.core.types.Predicate;


import java.util.ArrayList;
import java.util.List;
Expand All @@ -21,10 +26,12 @@ public class UserController {

private final IUserDao api;
private final UserRepository repo;
private final MyUserRepository myUserRepository;
@Autowired
public UserController(IUserDao api, UserRepository repo) {
public UserController(IUserDao api, UserRepository repo, MyUserRepository myUserRepository) {
this.api = api;
this.repo = repo;
this.myUserRepository = myUserRepository;
}

@GetMapping("/users") //users?search=lastName:Bozenka,age>25
Expand All @@ -44,7 +51,7 @@ public List<User> findAll(@RequestParam(value = "search", required = false)Strin
@GetMapping("/users/specs") //users/specs?search=lastName:Bozenka,age>25
public List<User> search(@RequestParam(value = "search") String search) {
UserSpecificationBuilder builder = new UserSpecificationBuilder();
Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),");
Pattern pattern = Pattern.compile("(\\w+?)([:<>])(\\w+?),");
Matcher matcher = pattern.matcher(search + ",");
while (matcher.find()) {
builder.with(matcher.group(1), matcher.group(2), matcher.group(3));
Expand All @@ -53,4 +60,25 @@ public List<User> search(@RequestParam(value = "search") String search) {
Specification<User> spec = builder.build();
return repo.findAll(spec);
}

@RequestMapping(method = RequestMethod.GET, value = "/myusers")
@ResponseBody//http://localhost:8080/users?search=lastName:doe,age>25
public Iterable<MyUser> findAllByQuerydsl(@RequestParam(value = "search") String search) {
MyUserPredicateBuilder builder = new MyUserPredicateBuilder();
if (search != null) {
Pattern pattern = Pattern.compile("(\\w+?)([:<>])(\\w+?),");
Matcher matcher = pattern.matcher(search + ",");
while (matcher.find()) {
builder.with(matcher.group(1), matcher.group(2), matcher.group(3));
}
}
BooleanExpression exp = builder.build();
return myUserRepository.findAll(exp);
}

@RequestMapping(method = RequestMethod.GET, value = "/api/myusers")
@ResponseBody
public Iterable<MyUser> findAllByWebQuerydsl(@QuerydslPredicate(root = MyUser.class) Predicate predicate) {
return myUserRepository.findAll(predicate);
}
}
Loading

0 comments on commit 0dbaa86

Please sign in to comment.