Skip to content

Latest commit

 

History

History
185 lines (138 loc) · 6.25 KB

README.md

File metadata and controls

185 lines (138 loc) · 6.25 KB

Juery GitHub license

Quality Gate Status Coverage Maintainability Rating

Juery is a tiny Java library to manage search and filter query from user to database. api and basic packages have no dependencies. They contain everything you need to use Juery. The jooq package contains useful tools for projects using the jOOQ DSL.

Installation

Use the package manager maven to install juery.

<dependency>
    <groupId>fr.ght1pc9kc</groupId>
    <artifactId>juery-api</artifactId>
    <version>VERSION</version>
</dependency>
<dependency>
    <groupId>fr.ght1pc9kc</groupId>
    <artifactId>juery-basic</artifactId>
    <version>VERSION</version>
</dependency>
<dependency>
    <groupId>fr.ght1pc9kc</groupId>
    <artifactId>juery-jooq</artifactId>
    <version>VERSION</version>
</dependency>

for gradle

compile "fr.ght1pc9kc:juery-api:VERSION"
compile "fr.ght1pc9kc:juery-basic:VERSION"
compile "fr.ght1pc9kc:juery-jooq:VERSION"

Usage

Create Criteria and PageRequest manually

import fr.ght1pc9kc.juery.api.Criteria;

Criteria.property("jedi").eq("Obiwan")
    .and(Criteria.property("age").gt(40)
    .or(Criteria.property("age").lt(20)));
import fr.ght1pc9kc.juery.api.PageRequest;
import fr.ght1pc9kc.juery.api.pagination.Direction;
import fr.ght1pc9kc.juery.api.pagination.Order;
import fr.ght1pc9kc.juery.api.pagination.Sort;

PageRequest.builder()
    .page(2).size(100)
    .filter(Criteria.property("profile").eq("jedi").and(Criteria.property("job").eq("master")))
    .sort(Sort.of(new Order(Direction.ASC, "name"), new Order(Direction.DESC, "email")))
    .build();

Parsing a query string

Into the controller.

import fr.ght1pc9kc.juery.basic.QueryStringParser;

@GetMapping
public Flux<Feed> list(@RequestParam Map<String, String> queryStringParams) {
        return feedService.list(QueryStringParser.withDefaultConfig().parse(queryStringParams))
        .onErrorMap(BadCriteriaFilter.class, e -> new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getLocalizedMessage()));
}

QueryStringParser will transform the query string into a PageRequest which contains a Criteria. Depending on your architecture, the object will traverse layers until persistence. It can be enriched in the process by with methods which create a new enriched object. All the API is strictly immutable.

Since 1.2.0: You can now, configure the QueryStringParser to customize the querystring parameters used :

import fr.ght1pc9kc.juery.basic.ParserConfiguration;
        
ParserConfiguration config = ParserConfiguration.builder()
        .page("_pg")
        .size("_sz")
        .from("_fr")
        .to("_to")
        .sort("_st")
        .maxPageSize(20)
        .build();

QueryStringParser.withConfig(config).parse(queryStringParams);

Filtering

In the persistence layer we will be able to use Visitors as follows.

import fr.ght1pc9kc.juery.jooq.filter.JooqConditionVisitor;

private static final JooqConditionVisitor JOOQ_CONDITION_VISITOR =
        new JooqConditionVisitor(PropertiesMappers.FEEDS_PROPERTIES_MAPPING::get);

The JooqConditionVisitor implementation takes as input a Function <String, Field <?>> which will allow to transform the properties of your criteria, into jOOQ Field objects corresponding to columns of your tables.

import fr.ght1pc9kc.juery.api.Criteria;
import fr.ght1pc9kc.juery.api.PageRequest;

// transforms the Criteria present in pageRequest into Condition
Condition conditions = pageRequest.filter.visit(JOOQ_CONDITION_VISITOR);

// Execute query with the conditions generated by the visitor 
Cursor<Record> cursor = dsl
    .select(FEEDS.fields()).select(FEEDS_USERS.FEUS_TAGS)
        .from(FEEDS)
        .leftJoin(FEEDS_USERS).on(FEEDS_USERS.FEUS_FEED_ID.eq(FEEDS.FEED_ID))
        .where(conditions).fetchLazy();

Pagination

The PageRequest object contains the data necessary for pagination. You can implement it yourself, but for jOOQ users, the JooqPagination helper makes it easier.

import fr.ght1pc9kc.juery.api.Criteria;
import fr.ght1pc9kc.juery.api.PageRequest;

// transforms the Criteria present in pageRequest into Condition
Condition conditions = pageRequest.filter.visit(NEWS_CONDITION_VISITOR);

// Apply pagination parameters to the query
final Select<Record> query = JooqPagination.apply(pageRequest, PropertiesMappers.FEEDS_PROPERTIES_MAPPING, dsl
    .select(FEEDS.fields()).select(FEEDS_USERS.FEUS_TAGS)
        .from(FEEDS)
        .leftJoin(FEEDS_USERS).on(FEEDS_USERS.FEUS_FEED_ID.eq(FEEDS.FEED_ID))
        .where(conditions)
);

Cursor<Record> cursor = query.fetchLazy();

We find the PropertiesMappers.FEEDS_PROPERTIES_MAPPING, optional, which allows to make the link between the sort criteria and the table fields.

PropertiesMappers example

As an example to illustrate what is PropertiesMappers.FEEDS_PROPERTIES_MAPPING in the context of using jOOQ as DSL.

public static final Map<String, Field<?>> FEEDS_PROPERTIES_MAPPING = Map.of(
        "id", FEEDS.FEED_ID,
        "name", FEEDS.FEED_NAME,
        ...
);

FEEDS was a jOOQ Table generated before compilation with jooq-codegen-maven Maven Plugin. "id" and "name" was properties used in Criteria.

import fr.ght1pc9kc.juery.api.Criteria;

Criteria.property("id").eq("F0042")
    .and(Criteria.property("name").eq("H2G2"));

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

MIT