diff --git a/pom.xml b/pom.xml index 2ad795b..e64fa1e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.struchkov.haiti.filter haiti-filter-jooq - 0.1.0 + 0.2.0 jar Haiti Filter JOOQ @@ -23,7 +23,7 @@ 11 11 - 3.15.5 + 3.16.1 1.6.8 3.2.1 @@ -36,7 +36,7 @@ dev.struchkov.haiti haiti-bom - 0.0.1-RELEASE + 0.0.2 pom import @@ -48,6 +48,10 @@ dev.struchkov.haiti haiti-filter + + dev.struchkov.haiti + haiti-utils + org.jooq jooq diff --git a/src/main/java/dev/struchkov/haiti/filter/jooq/CriteriaJooqFilter.java b/src/main/java/dev/struchkov/haiti/filter/jooq/CriteriaJooqFilter.java index 665eaeb..9e20e1c 100644 --- a/src/main/java/dev/struchkov/haiti/filter/jooq/CriteriaJooqFilter.java +++ b/src/main/java/dev/struchkov/haiti/filter/jooq/CriteriaJooqFilter.java @@ -2,6 +2,10 @@ package dev.struchkov.haiti.filter.jooq; import dev.struchkov.haiti.filter.Filter; import dev.struchkov.haiti.filter.FilterQuery; +import dev.struchkov.haiti.filter.jooq.exception.FilterJooqHaitiException; +import dev.struchkov.haiti.filter.jooq.page.PageableOffset; +import dev.struchkov.haiti.filter.jooq.page.PageableSeek; +import dev.struchkov.haiti.utils.Assert; import lombok.NonNull; import org.jooq.Condition; import org.jooq.DSLContext; @@ -10,12 +14,12 @@ import org.jooq.Query; import org.jooq.Record; import org.jooq.SelectConditionStep; import org.jooq.SelectJoinStep; +import org.jooq.SelectSeekStepN; +import org.jooq.SortField; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.function.Consumer; -import java.util.stream.Collectors; import static org.jooq.impl.DSL.condition; import static org.jooq.impl.DSL.field; @@ -27,13 +31,13 @@ public class CriteriaJooqFilter implements Filter { private final List notConditions = new ArrayList<>(); private final List joinTables = new ArrayList<>(); - private String fieldOrder; - private Object lastId; - private Integer pageSize; - private final String table; private final DSLContext dsl; + private PageableOffset offset; + private PageableSeek seek; + private List sorts = new ArrayList<>(); + protected CriteriaJooqFilter(String table, DSLContext dsl) { this.table = table; this.dsl = dsl; @@ -82,10 +86,36 @@ public class CriteriaJooqFilter implements Filter { throw new IllegalStateException("Операция отрицания пока не поддерживается"); } - public Filter page(@NonNull String fieldOrder, Object id, int pageSize) { - this.fieldOrder = fieldOrder; - this.lastId = id; - this.pageSize = pageSize; + public Filter page(@NonNull PageableOffset offset) { + Assert.isNull(seek, () -> new FilterJooqHaitiException("Нельзя установить два типа пагинации одновременно")); + this.offset = offset; + return this; + } + + public Filter page(@NonNull PageableSeek seek) { + Assert.isNull(offset, () -> new FilterJooqHaitiException("Нельзя установить два типа пагинации одновременно")); + this.seek = seek; + return this; + } + + public Filter sort(@NonNull SortContainer container) { + if (container.getFieldName() != null) { + this.sorts.add(container); + } + return this; + } + + public Filter sort(String field, SortType sortType) { + if (field != null) { + this.sorts.add(SortContainer.of(field, sortType)); + } + return this; + } + + public Filter sort(String field) { + if (field != null) { + this.sorts.add(SortContainer.of(field)); + } return this; } @@ -135,17 +165,53 @@ public class CriteriaJooqFilter implements Filter { } } final SelectConditionStep where = from.where(conditions); - if (pageSize != null && fieldOrder != null) { - if (lastId != null) { - where.orderBy(field(fieldOrder)) - .seek(lastId) - .limit(pageSize); - } else { - where.orderBy(field(fieldOrder)) - .limit(pageSize); - } - } + final SelectSeekStepN sort = setSort(where); + setPaginationOffset(where); + setPaginationSeek(sort); return where; } + private SelectSeekStepN setSort(SelectConditionStep where) { + if (!sorts.isEmpty()) { + final List> newSorts = new ArrayList<>(); + for (SortContainer sort : sorts) { + final SortType sortType = sort.getType(); + final String fieldName = sort.getFieldName(); + if (SortType.ASC.equals(sortType)) { + newSorts.add(field(fieldName).asc()); + } else { + newSorts.add(field(fieldName).desc()); + } + } + return where.orderBy(newSorts); + } + return null; + } + + private void setPaginationSeek(SelectSeekStepN sort) { + if (seek != null) { + Assert.isNotNull(sort, () -> new FilterJooqHaitiException("При использовании пагинации типа seek необходимо указать сортировку")); + final Integer pageSize = seek.getPageSize(); + final Object lastId = seek.getLastId(); + if (pageSize != null) { + if (lastId != null) { + sort + .seek(lastId) + .limit(pageSize); + } else { + sort + .limit(pageSize); + } + } + } + } + + private void setPaginationOffset(SelectConditionStep where) { + if (offset != null) { + final int pageNumber = offset.getPageNumber(); + final int pageSize = offset.getPageSize(); + final int offsetNumber = (pageNumber + 1) * pageSize - pageSize; + where.limit(pageSize).offset(offsetNumber); + } + } } diff --git a/src/main/java/dev/struchkov/haiti/filter/jooq/SortContainer.java b/src/main/java/dev/struchkov/haiti/filter/jooq/SortContainer.java new file mode 100644 index 0000000..4f97afb --- /dev/null +++ b/src/main/java/dev/struchkov/haiti/filter/jooq/SortContainer.java @@ -0,0 +1,29 @@ +package dev.struchkov.haiti.filter.jooq; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class SortContainer { + + private final String fieldName; + private SortType type = SortType.ASC; + + public static SortContainer empty() { + return new SortContainer(null); + } + + public static SortContainer of(@NonNull String fieldName) { + return new SortContainer(fieldName); + } + + public static SortContainer of(@NonNull String fieldName, SortType sortType) { + return new SortContainer(fieldName, sortType == null ? SortType.ASC : sortType); + } + +} diff --git a/src/main/java/dev/struchkov/haiti/filter/jooq/SortType.java b/src/main/java/dev/struchkov/haiti/filter/jooq/SortType.java new file mode 100644 index 0000000..88cda08 --- /dev/null +++ b/src/main/java/dev/struchkov/haiti/filter/jooq/SortType.java @@ -0,0 +1,7 @@ +package dev.struchkov.haiti.filter.jooq; + +public enum SortType { + + ASC, DESC + +} diff --git a/src/main/java/dev/struchkov/haiti/filter/jooq/exception/FilterJooqHaitiException.java b/src/main/java/dev/struchkov/haiti/filter/jooq/exception/FilterJooqHaitiException.java new file mode 100644 index 0000000..ebf9c3e --- /dev/null +++ b/src/main/java/dev/struchkov/haiti/filter/jooq/exception/FilterJooqHaitiException.java @@ -0,0 +1,11 @@ +package dev.struchkov.haiti.filter.jooq.exception; + +import dev.struchkov.haiti.filter.exception.FilterException; + +public class FilterJooqHaitiException extends FilterException { + + public FilterJooqHaitiException(String message) { + super(message); + } + +} diff --git a/src/main/java/dev/struchkov/haiti/filter/jooq/page/PageableOffset.java b/src/main/java/dev/struchkov/haiti/filter/jooq/page/PageableOffset.java new file mode 100644 index 0000000..af0fd16 --- /dev/null +++ b/src/main/java/dev/struchkov/haiti/filter/jooq/page/PageableOffset.java @@ -0,0 +1,24 @@ +package dev.struchkov.haiti.filter.jooq.page; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class PageableOffset { + + private final int pageNumber; + private int pageSize = 30; + + public static PageableOffset of(int pageNumber) { + return new PageableOffset(pageNumber); + } + + public static PageableOffset of(int pageNumber, int pageSize) { + return new PageableOffset(pageNumber, pageSize); + } + +} diff --git a/src/main/java/dev/struchkov/haiti/filter/jooq/page/PageableSeek.java b/src/main/java/dev/struchkov/haiti/filter/jooq/page/PageableSeek.java new file mode 100644 index 0000000..b00ee0a --- /dev/null +++ b/src/main/java/dev/struchkov/haiti/filter/jooq/page/PageableSeek.java @@ -0,0 +1,33 @@ +package dev.struchkov.haiti.filter.jooq.page; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class PageableSeek { + + private final Object lastId; + private int pageSize = 30; + + public static PageableSeek empty() { + return new PageableSeek(null); + } + + public static PageableSeek of(int pageSize) { + return new PageableSeek(null, pageSize); + } + + public static PageableSeek of(@NonNull Object lastId) { + return new PageableSeek(lastId); + } + + public static PageableSeek of(@NonNull Object lastId, int pageSize) { + return new PageableSeek(lastId, pageSize); + } + +}