All Projects → wenhao → Jpa Spec

wenhao / Jpa Spec

Licence: mit
A JPA Query By Specification framework.

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to Jpa Spec

spring-data-jpa-mongodb-expressions
Use the MongoDB query language to query your relational database, typically from frontend.
Stars: ✭ 86 (-86.13%)
Mutual labels:  jpa, hibernate, spring-data-jpa
Jplusone
Tool for automatic detection and asserting "N+1 SELECT problem" occurences in JPA based Spring Boot Java applications and finding origin of JPA issued SQL statements in general
Stars: ✭ 91 (-85.32%)
Mutual labels:  hibernate, jpa, spring-data-jpa
Spring Framework Petclinic
A Spring Framework application based on JSP, Spring MVC, Spring Data JPA, Hibernate and JDBC
Stars: ✭ 251 (-59.52%)
Mutual labels:  hibernate, jpa, spring-data-jpa
Spring Boot Mysql Rest Api Tutorial
Building a Restful CRUD API using Spring Boot, Mysql, JPA and Hibernate
Stars: ✭ 279 (-55%)
Mutual labels:  hibernate, jpa, spring-data-jpa
Spring-Boot-2
Spring Boot 2.x examples
Stars: ✭ 33 (-94.68%)
Mutual labels:  jpa, hibernate, spring-data-jpa
Angularjs Springmvc Sample Boot
A RESTful sample using Spring Boot, Spring MVC, Spring Data and Angular/Bootstrap.
Stars: ✭ 309 (-50.16%)
Mutual labels:  hibernate, jpa, spring-data-jpa
vogon-java
Vogon - A simple personal finance tracker using Spring Boot and AngularJS
Stars: ✭ 16 (-97.42%)
Mutual labels:  jpa, hibernate, spring-data-jpa
spring-discord-bot
Discord all-purpose bot, made using Spring Boot, JPA, Hibernate, REST, HikariCP. Written for fun, do not take this serious.
Stars: ✭ 26 (-95.81%)
Mutual labels:  jpa, hibernate, spring-data-jpa
Micronaut Data
Ahead of Time Data Repositories
Stars: ✭ 352 (-43.23%)
Mutual labels:  hibernate, jpa
jpa2ddl
JPA Schema Generator Plugin
Stars: ✭ 104 (-83.23%)
Mutual labels:  jpa, hibernate
Hibernate Springboot
Collection of best practices for Java persistence performance in Spring Boot applications
Stars: ✭ 589 (-5%)
Mutual labels:  hibernate, jpa
Jeddict
Jakarta EE 8 (Java EE) & MicroProfile 3.2 application generator and modeler
Stars: ✭ 358 (-42.26%)
Mutual labels:  hibernate, jpa
Jooq
jOOQ is the best way to write SQL in Java
Stars: ✭ 4,695 (+657.26%)
Mutual labels:  hibernate, jpa
FluentJPA
Fluent API for writing typesafe SQL queries in Java for JPA.
Stars: ✭ 87 (-85.97%)
Mutual labels:  jpa, hibernate
spring-boot-jpa
A Spring Boot microservices reference application using Spring Data JPA
Stars: ✭ 25 (-95.97%)
Mutual labels:  jpa, hibernate
BusinessInfrastructurePlatformGroupVersion
A java web project based on Spring Boot using MySQL, Spring MVC, Hibernate, Spring Data JPA, Query DSL, Lombok, Logback, etc.
Stars: ✭ 90 (-85.48%)
Mutual labels:  hibernate, spring-data-jpa
Spring Petclinic Rest
REST version of the Spring Petclinic sample application
Stars: ✭ 257 (-58.55%)
Mutual labels:  hibernate, spring-data-jpa
jpa-manytomany-extracolumns-springboot-maven-mysql
JPA Many-To-Many Extra Columns Relationship Mapping Example with Spring Boot, Maven and MySQL
Stars: ✭ 15 (-97.58%)
Mutual labels:  jpa, spring-data-jpa
spring-jpa-hibernate-mysql-example
Spring Data JPA with Hibernate using MySql Example
Stars: ✭ 24 (-96.13%)
Mutual labels:  hibernate, spring-data-jpa
Hibernate Orm
Hibernate's core Object/Relational Mapping functionality
Stars: ✭ 4,806 (+675.16%)
Mutual labels:  hibernate, jpa

Build Status codecov Quality Gate Status FOSSA Status codebeat badge CII Best Practices MIT

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

English Version Chinese Version
Latest 最新
3.2.5 3.2.5_cn
3.2.1 3.2.1_cn
3.1.0 3.1.0_cn
3.0.0 3.0.0_cn

Gradle

repositories {
    jcenter()
}

dependencies {
    implementation 'com.github.wenhao:jpa-spec:3.2.5'
}

Maven

<dependency>
    <groupId>com.github.wenhao</groupId>
    <artifactId>jpa-spec</artifactId>
    <version>3.2.5</version>
</dependency>

Build

./gradlew clean build

Specification By Examples:

Each specification support three parameters:

  1. condition: if true(default), apply this specification.
  2. property: field name.
  3. 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<Person, Long>, JpaSpecificationExecutor<Person> {
}    
public Page<Person> findAll(SearchRequest request) {
    Specification<Person> specification = Specifications.<Person>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.

Test: EqualTest.java and NotEqualTest.java

public List<Person> findAll(SearchRequest request) {
    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)
            .build();

    return personRepository.findAll(specification);
}

In/NotIn Example

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

Test: InTest.java

public List<Person> findAll(SearchRequest request) {
    Specification<Person> specification = Specifications.<Person>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.

Test: GreatThanTest.java

public List<Person> findAll(SearchRequest request) {
    Specification<Person> specification = Specifications.<Person>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.

Test: BetweenTest.java

public List<Person> findAll(SearchRequest request) {
    Specification<Person> specification = Specifications.<Person>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%.

Test: LikeTest.java and NotLikeTest.java

public Page<Person> findAll(SearchRequest request) {
    Specification<Person> specification = Specifications.<Person>and()
            .like("name", "ac", "%og%")
            .notLike("company", "ec")
            .build();

    return personRepository.findAll(specification);
}

Or

support or specifications.

Test: OrTest.java

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

    return phoneRepository.findAll(specification);
}

Mixed And and Or

support mixed and and or specifications.

Test: AndOrTest.java

public List<Person> findAll(SearchRequest request) {
    Specification<Person> specification = Specifications.<Person>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.

Test: JoinTest.java

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

public List<Phone> findAll(SearchRequest request) {
    Specification<Phone> specification = Specifications.<Phone>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<Phone> findAll(SearchRequest request) {
    Specification<Person> specification = Specifications.<Person>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".

Test: PredicateTest.java

public List<Phone> findAll(SearchRequest request) {
    Specification<Phone> specification = Specifications.<Phone>and()
        .eq(StringUtils.isNotBlank(request.getBrand()), "brand", "HuaWei")
        .predicate(StringUtils.isNotBlank(request.getPersonName()), (root, query, cb) -> {
            Path<Person> 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.

Test: PredicateTest.java

public List<Phone> findAll(SearchRequest request) {
    Specification<Person> specification = Specifications.<Person>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

Test: SortTest.java

public List<Person> findAll(SearchRequest request) {
    Specification<Person> specification = Specifications.<Person>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<Person> findAll(SearchRequest request) {
    Specification<Person> specification = Specifications.<Person>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.

Test: VirtualViewTest.java

@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<PersonIdCard> findAll(SearchRequest request) {
    Specification<PersonIdCard> specification = Specifications.<PersonIdCard>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

FOSSA Status

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].