Skip to content

Commit

Permalink
Merge pull request wenhao#4 from marcinsoja/master
Browse files Browse the repository at this point in the history
Merge refactor code.
  • Loading branch information
wenhao committed Mar 7, 2017
2 parents c0bb447 + ad074b7 commit 223e8ba
Show file tree
Hide file tree
Showing 21 changed files with 208 additions and 437 deletions.
36 changes: 17 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public interface PersonRepository extends JpaRepository<Person, Long>, JpaSpecif

```java
public Page<Person> findAll(SearchRequest request) {
Specification<Person> specification = Specifications.<Person>builder()
Specification<Person> specification = Specifications.<Person>and()
.eq(StringUtils.isNotBlank(request.getName()), "name", request.getName())
.gt(Objects.nonNull(request.getAge()), "age", 18)
.between("birthday", new Range<>(new Date(), new Date()))
Expand All @@ -75,7 +75,7 @@ find any person nickName equals to "dog" and name equals to "Jack"/"Eric" or nul

```java
public List<Person> findAll(SearchRequest request) {
Specification<Person> specification = Specifications.<Person>builder()
Specification<Person> specification = Specifications.<Person>and()
.eq("nickName", "dog")
.eq(StringUtils.isNotBlank(request.getName()), "name", "Jack", "Eric", null)
.eq("company", null) //or eq("company", (Object) null)
Expand All @@ -93,7 +93,7 @@ find any person name in "Jack" or "Eric" and company not in "ThoughtWorks" or "I

```java
public List<Person> findAll(SearchRequest request) {
Specification<Person> specification = Specifications.<Person>builder()
Specification<Person> specification = Specifications.<Person>and()
.in("name", request.getNames().toArray()) //or in("name", "Jack", "Eric")
.notIn("company", "ThoughtWorks", "IBM")
.build();
Expand All @@ -110,7 +110,7 @@ find any people age bigger than 18.

```java
public List<Person> findAll(SearchRequest request) {
Specification<Person> specification = Specifications.<Person>builder()
Specification<Person> specification = Specifications.<Person>and()
.gt(Objects.nonNull(request.getAge()), "age", 18)
.build();

Expand All @@ -126,7 +126,7 @@ find any person age between 18 and 25, birthday between someday and someday.

```java
public List<Person> findAll(SearchRequest request) {
Specification<Person> specification = Specifications.<Person>builder()
Specification<Person> specification = Specifications.<Person>and()
.between(Objects.nonNull(request.getAge(), "age", new Range<>(18, 25))
.between("birthday", new Range<>(new Date(), new Date()))
.build();
Expand All @@ -143,7 +143,7 @@ find any person name like %ac% or %og%, company not like %ec%.

```java
public Page<Person> findAll(SearchRequest request) {
Specification<Person> specification = Specifications.<Person>builder()
Specification<Person> specification = Specifications.<Person>and()
.like("name", "ac", "%og%")
.notLike("company", "ec")
.build();
Expand All @@ -160,12 +160,10 @@ support or specifications.

```java
public List<Phone> findAll(SearchRequest request) {
Specification<Person> specification = Specifications.<Person>builder()
.and(OrSpecifications.<Person>builder()
Specification<Person> specification = Specifications.<Person>or()
.like("name", "%ac%")
.gt("age", 19)
.build())
.build();
.build();

return phoneRepository.findAll(specification);
}
Expand All @@ -181,7 +179,7 @@ each specification support association query as left join.

```java
public List<Phone> findAll(SearchRequest request) {
Specification<Phone> specification = Specifications.<Phone>builder()
Specification<Phone> specification = Specifications.<Phone>and()
.eq(StringUtils.isNotBlank(request.getBrand()), "brand", "HuaWei")
.eq(StringUtils.isNotBlank(request.getPersonName()), "person.name", "Jack")
.build();
Expand All @@ -194,7 +192,7 @@ public List<Phone> findAll(SearchRequest request) {

```java
public List<Phone> findAll(SearchRequest request) {
Specification<Person> specification = Specifications.<Person>builder()
Specification<Person> specification = Specifications.<Person>and()
.between("age", new Range<>(10, 35))
.eq(StringUtils.isNotBlank(jack.getName()), "addresses.street", "Chengdu")
.build();
Expand All @@ -213,9 +211,9 @@ You can custom specification to do the @ManyToOne and @ManyToMany as well.

```java
public List<Phone> findAll(SearchRequest request) {
Specification<Phone> specification = Specifications.<Phone>builder()
Specification<Phone> specification = Specifications.<Phone>and()
.eq(StringUtils.isNotBlank(request.getBrand()), "brand", "HuaWei")
.and(StringUtils.isNotBlank(request.getPersonName()), (root, query, cb) -> {
.predicate(StringUtils.isNotBlank(request.getPersonName()), (root, query, cb) -> {
Path<Person> person = root.get("person");
return cb.equal(person.get("name"), "Jack");
})
Expand All @@ -231,9 +229,9 @@ public List<Phone> findAll(SearchRequest request) {

```java
public List<Phone> findAll(SearchRequest request) {
Specification<Person> specification = Specifications.<Person>builder()
Specification<Person> specification = Specifications.<Person>and()
.between("age", new Range<>(10, 35))
.and(StringUtils.isNotBlank(jack.getName()), ((root, query, cb) -> {
.predicate(StringUtils.isNotBlank(jack.getName()), ((root, query, cb) -> {
Join address = root.join("addresses", JoinType.LEFT);
return cb.equal(address.get("street"), "Chengdu");
}))
Expand All @@ -249,7 +247,7 @@ public List<Phone> findAll(SearchRequest request) {

```java
public List<Person> findAll(SearchRequest request) {
Specification<Person> specification = Specifications.<Person>builder()
Specification<Person> specification = Specifications.<Person>and()
.eq(StringUtils.isNotBlank(request.getName()), "name", request.getName())
.gt("age", 18)
.between("birthday", new Range<>(new Date(), new Date()))
Expand All @@ -271,7 +269,7 @@ find person by pagination and sort by name desc and birthday asc.

```java
public Page<Person> findAll(SearchRequest request) {
Specification<Person> specification = Specifications.<Person>builder()
Specification<Person> specification = Specifications.<Person>and()
.eq(StringUtils.isNotBlank(request.getName()), "name", request.getName())
.gt("age", 18)
.between("birthday", new Range<>(new Date(), new Date()))
Expand Down Expand Up @@ -315,7 +313,7 @@ public class PersonIdCard {
```java
public List<PersonIdCard> findAll(SearchRequest request) {
Specification<PersonIdCard> specification = Specifications.<PersonIdCard>builder()
Specification<PersonIdCard> specification = Specifications.<PersonIdCard>and()
.gt(Objects.nonNull(request.getAge()), "age", 18)
.build();
Expand Down
152 changes: 152 additions & 0 deletions src/main/java/com/github/wenhao/jpa/Builder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package com.github.wenhao.jpa;

import com.github.wenhao.jpa.specification.BetweenSpecification;
import com.github.wenhao.jpa.specification.EqualSpecification;
import com.github.wenhao.jpa.specification.GeSpecification;
import com.github.wenhao.jpa.specification.GtSpecification;
import com.github.wenhao.jpa.specification.InSpecification;
import com.github.wenhao.jpa.specification.LeSpecification;
import com.github.wenhao.jpa.specification.LikeSpecification;
import com.github.wenhao.jpa.specification.LtSpecification;
import com.github.wenhao.jpa.specification.NotEqualSpecification;
import com.github.wenhao.jpa.specification.NotInSpecification;
import com.github.wenhao.jpa.specification.NotLikeSpecification;
import org.springframework.data.domain.Range;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

import static javax.persistence.criteria.Predicate.BooleanOperator.OR;

public class Builder<T> {

private final Predicate.BooleanOperator operator;

private List<Specification<T>> specifications;

public Builder(Predicate.BooleanOperator operator) {
this.operator = operator;
this.specifications = new ArrayList<>();
}

public Builder<T> eq(String property, Object... values) {
return eq(true, property, values);
}

public Builder<T> eq(boolean condition, String property, Object... values) {
return this.predicate(condition, new EqualSpecification<T>(property, values));
}

public Builder<T> ne(String property, Object... values) {
return ne(true, property, values);
}

public Builder<T> ne(boolean condition, String property, Object... values) {
return this.predicate(condition, new NotEqualSpecification<T>(property, values));
}

public Builder<T> gt(String property, Number number) {
return gt(true, property, number);
}

public Builder<T> gt(boolean condition, String property, Number number) {
return this.predicate(condition, new GtSpecification<T>(property, number));
}

public Builder<T> ge(String property, Number number) {
return ge(true, property, number);
}

public Builder<T> ge(boolean condition, String property, Number number) {
return this.predicate(condition, new GeSpecification<T>(property, number));
}

public Builder<T> lt(String property, Number number) {
return lt(true, property, number);
}

public Builder<T> lt(boolean condition, String property, Number number) {
return this.predicate(condition, new LtSpecification<T>(property, number));
}

public Builder<T> le(String property, Number number) {
return le(true, property, number);
}

public Builder<T> le(boolean condition, String property, Number number) {
return this.predicate(condition, new LeSpecification<T>(property, number));
}

public Builder<T> between(String property, Range<? extends Comparable<?>> range) {
return between(true, property, range);
}

public Builder<T> between(boolean condition, String property, Range<? extends Comparable<?>> range) {
return this.predicate(condition, new BetweenSpecification<T>(property, range));
}

public Builder<T> like(String property, String... patterns) {
return like(true, property, patterns);
}

public Builder<T> like(boolean condition, String property, String... patterns) {
return this.predicate(condition, new LikeSpecification<T>(property, patterns));
}

public Builder<T> notLike(String property, String... patterns) {
return notLike(true, property, patterns);
}

public Builder<T> notLike(boolean condition, String property, String... patterns) {
return this.predicate(condition, new NotLikeSpecification<T>(property, patterns));
}

public Builder<T> in(String property, Object... values) {
return this.in(true, property, values);
}

public Builder<T> in(boolean condition, String property, Object... values) {
return this.predicate(condition, new InSpecification<T>(property, values));
}

public Builder<T> notIn(String property, Object... values) {
return this.notIn(true, property, values);
}

public Builder<T> notIn(boolean condition, String property, Object... values) {
return this.predicate(condition, new NotInSpecification<T>(property, values));
}

public Builder<T> predicate(Specification specification) {
return predicate(true, specification);
}

public Builder<T> predicate(boolean condition, Specification specification) {
if (condition) {
this.specifications.add(specification);
}
return this;
}

public Specification<T> build() {
return new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate[] predicates = new Predicate[specifications.size()];
for (int i = 0; i < specifications.size(); i++) {
predicates[i] = specifications.get(i).toPredicate(root, query, cb);
}
if(operator == OR) {
return cb.or(predicates);
} else {
return cb.and(predicates);
}
}
};
}
}
Loading

0 comments on commit 223e8ba

Please sign in to comment.