java jpa框架,jpa-spec一个JAP查询规范框架

68747470733a2f2f7472617669732d63692e6f72672f77656e68616f2f6a70612d737065632e7376673f6272616e63683d6d617374657268747470733a2f2f636f6465636f762e696f2f67682f77656e68616f2f6a70612d737065632f6272616e63682f6d61737465722f67726170682f62616467652e73766768747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d77656e68616f5f6a70612d73706563266d65747269633d616c6572745f73746174757368747470733a2f2f6170702e666f7373612e696f2f6170692f70726f6a656374732f6769742532426769746875622e636f6d25324677656e68616f2532466a70612d737065632e7376673f747970653d736869656c6468747470733a2f2f636f6465626561742e636f2f6261646765732f35396662353535622d666632652d343534372d386333362d64656363346230353631366368747470733a2f2f626573747072616374696365732e636f7265696e6672617374727563747572652e6f72672f70726f6a656374732f333035322f626164676568747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e

jpa-spec

Inspired by Legacy Hibernate Criteria Queries, while this should be considered deprecated vs JPA APIs,

but it still productive and easily understandable. Build on Spring Data JPA and simplify the dynamic query process.

Features

Compatible with Spring Data JPA and JPA 2.1 interface.

Equal/NotEqual/Like/NotLike/In/NotIn support multiple values, Equal/NotEqual support Null value.

Each specification support join query(left joiner).

Support custom specification.

Builder style specification creator.

Support pagination and sort builder.

Docs

Gradle

repositories {

jcenter()

}

dependencies {

implementation 'com.github.wenhao:jpa-spec:3.2.5'

}

Maven

com.github.wenhao

jpa-spec

3.2.5

Build

./gradlew clean build

Specification By Examples:

Each specification support three parameters:

condition: if true(default), apply this specification.

property: field name.

values: compare value with model, eq/ne/like support multiple values.

General Example

each Repository class should extends from two super class JpaRepository and JpaSpecificationExecutor.

public interface PersonRepository extends JpaRepository, JpaSpecificationExecutor {

}

public Page findAll(SearchRequest request) {

Specification specification = Specifications.and()

.eq(StringUtils.isNotBlank(request.getName()), "name", request.getName())

.gt(Objects.nonNull(request.getAge()), "age", 18)

.between("birthday", new Date(), new Date())

.like("nickName", "%og%", "%me")

.build();

return personRepository.findAll(specification, new PageRequest(0, 15));

}

Equal/NotEqual Example

find any person nickName equals to "dog" and name equals to "Jack"/"Eric" or null value, and company is null.

public List findAll(SearchRequest request) {

Specification specification = Specifications.and()

.eq("nickName", "dog")

.eq(StringUtils.isNotBlank(request.getName()), "name", "Jack", "Eric", null)

.eq("company", null) //or eq("company", (Object) null)

.build();

return personRepository.findAll(specification);

}

In/NotIn Example

find any person name in "Jack" or "Eric" and company not in "ThoughtWorks" or "IBM".

public List findAll(SearchRequest request) {

Specification specification = Specifications.and()

.in("name", request.getNames())

.notIn("company", Arrays.asList("ThoughtWorks", "IBM"))

.build();

return personRepository.findAll(specification);

}

Comparison Example

Support any comparison class which implements Comparable interface, find any people age bigger than 18.

public List findAll(SearchRequest request) {

Specification specification = Specifications.and()

.gt(Objects.nonNull(request.getAge()), "age", 18)

.lt("birthday", new Date())

.build();

return personRepository.findAll(specification);

}

Between Example

find any person age between 18 and 25, birthday between someday and someday.

public List findAll(SearchRequest request) {

Specification specification = Specifications.and()

.between(Objects.nonNull(request.getAge(), "age", 18, 25)

.between("birthday", new Date(), new Date())

.build();

return personRepository.findAll(specification);

}

Like/NotLike Example

find any person name like %ac% or %og%, company not like %ec%.

public Page findAll(SearchRequest request) {

Specification specification = Specifications.and()

.like("name", "ac", "%og%")

.notLike("company", "ec")

.build();

return personRepository.findAll(specification);

}

Or

support or specifications.

public List findAll(SearchRequest request) {

Specification specification = Specifications.or()

.like("name", "%ac%")

.gt("age", 19)

.build();

return phoneRepository.findAll(specification);

}

Mixed And and Or

support mixed and and or specifications.

public List findAll(SearchRequest request) {

Specification specification = Specifications.and()

.like("name", "%ac%")

.predicate(Specifications.or()

.lt("age", 19)

.gt("age", 25)

.build())

.build();

return personRepository.findAll(specification);

}

Join

each specification support association query as left join.

@ManyToOne association query, find person name equals to "Jack" and phone brand equals to "HuaWei".

public List findAll(SearchRequest request) {

Specification specification = Specifications.and()

.eq(StringUtils.isNotBlank(request.getBrand()), "brand", "HuaWei")

.eq(StringUtils.isNotBlank(request.getPersonName()), "person.name", "Jack")

.build();

return phoneRepository.findAll(specification);

}

@ManyToMany association query, find person age between 10 and 35, live in "Chengdu" street.

public List findAll(SearchRequest request) {

Specification specification = Specifications.and()

.between("age", 10, 35)

.eq(StringUtils.isNotBlank(jack.getName()), "addresses.street", "Chengdu")

.build();

return phoneRepository.findAll(specification);

}

Custom Specification

You can custom specification to do the @ManyToOne and @ManyToMany as well.

@ManyToOne association query, find person name equals to "Jack" and phone brand equals to "HuaWei".

public List findAll(SearchRequest request) {

Specification specification = Specifications.and()

.eq(StringUtils.isNotBlank(request.getBrand()), "brand", "HuaWei")

.predicate(StringUtils.isNotBlank(request.getPersonName()), (root, query, cb) -> {

Path person = root.get("person");

return cb.equal(person.get("name"), "Jack");

})

.build();

return phoneRepository.findAll(specification);

}

@ManyToMany association query, find person age between 10 and 35, live in "Chengdu" street.

public List findAll(SearchRequest request) {

Specification specification = Specifications.and()

.between("age", 10, 35)

.predicate(StringUtils.isNotBlank(jack.getName()), ((root, query, cb) -> {

Join address = root.join("addresses", JoinType.LEFT);

return cb.equal(address.get("street"), "Chengdu");

}))

.build();

return phoneRepository.findAll(specification);

}

Sort

public List findAll(SearchRequest request) {

Specification specification = Specifications.and()

.eq(StringUtils.isNotBlank(request.getName()), "name", request.getName())

.gt("age", 18)

.between("birthday", new Date(), new Date())

.like("nickName", "%og%")

.build();

Sort sort = Sorts.builder()

.desc(StringUtils.isNotBlank(request.getName()), "name")

.asc("birthday")

.build();

return personRepository.findAll(specification, sort);

}

Pagination

find person by pagination and sort by name desc and birthday asc.

public Page findAll(SearchRequest request) {

Specification specification = Specifications.and()

.eq(StringUtils.isNotBlank(request.getName()), "name", request.getName())

.gt("age", 18)

.between("birthday", new Date(), new Date())

.like("nickName", "%og%")

.build();

Sort sort = Sorts.builder()

.desc(StringUtils.isNotBlank(request.getName()), "name")

.asc("birthday")

.build();

return personRepository.findAll(specification, PageRequest.of(0, 15, sort));

}

Virtual View

Using @org.hibernate.annotations.Subselect to define a virtual view if you don't want a database table view.

There is no difference between a view and a database table for a Hibernate mapping.

@Entity

@Immutable

@Subselect("SELECT p.id, p.name, p.age, ic.number " +

"FROM person p " +

"LEFT JOIN id_card ic " +

"ON p.id_card_id=ic.id")

public class PersonIdCard {

@Id

private Long id;

private String name;

private Integer age;

private String number;

// Getters and setters are omitted for brevity

}

public List findAll(SearchRequest request) {

Specification specification = Specifications.and()

.gt(Objects.nonNull(request.getAge()), "age", 18)

.build();

return personIdCardRepository.findAll(specification);

}

Projection, GroupBy, Aggregation

Spring Data JPA doesn't support Projection(a little but trick), GroupBy and Aggregation,

furthermore, Projection/GroupBy/Aggregation are often used for complex statistics report, it might seem like overkill to use Hibernate/JPA ORM to solve it.

Alternatively, using virtual view and give a readable/significant class name to against your problem domain may be a better option.

Copyright and license

Copyright © 2016-2019 Wen Hao

Licensed under MIT License

68747470733a2f2f6170702e666f7373612e696f2f6170692f70726f6a656374732f6769742532426769746875622e636f6d25324677656e68616f2532466a70612d737065632e7376673f747970653d6c61726765

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值