diff --git a/README.md b/README.md index c681dc3..a591672 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Add this dependency in your pom.xml io.github.andersoncrocha jpql-query-builder - 1.2.1 + 1.2.2 ``` diff --git a/pom.xml b/pom.xml index 04c111e..2a6f441 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.andersoncrocha jpql-query-builder - 1.2.1 + 1.2.2 JPQL Query Builder This is a tool that helps you create queries with Hibernate using JPQL or native SQL diff --git a/src/main/java/io/github/andersoncrocha/jpqlquerybuilder/QueryBuilder.java b/src/main/java/io/github/andersoncrocha/jpqlquerybuilder/QueryBuilder.java index 9b679a4..517c2cb 100644 --- a/src/main/java/io/github/andersoncrocha/jpqlquerybuilder/QueryBuilder.java +++ b/src/main/java/io/github/andersoncrocha/jpqlquerybuilder/QueryBuilder.java @@ -11,6 +11,7 @@ import io.github.andersoncrocha.jpqlquerybuilder.operations.WhereGroup.Where; import io.github.andersoncrocha.jpqlquerybuilder.operations.types.JoinType; import io.github.andersoncrocha.jpqlquerybuilder.operations.types.QueryOperator; +import io.github.andersoncrocha.jpqlquerybuilder.operations.types.SortDirection; import io.github.andersoncrocha.jpqlquerybuilder.utils.StringUtils; import javax.persistence.EntityManager; @@ -24,6 +25,7 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Function; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; public class QueryBuilder { @@ -43,6 +45,10 @@ public class QueryBuilder { private QueryOperator lastOperator; private boolean nativeQuery; + public QueryBuilder() { + this(null); + } + public QueryBuilder(EntityManager entityManager) { this.entityManager = entityManager; this.joinGroup = new JoinGroup(); @@ -65,7 +71,7 @@ public QueryBuilder from(Class fromClass) { return this.from(fromClass, alias); } - public QueryBuilder from(Function subQueryFunction, String alias) { + public QueryBuilder from(UnaryOperator subQueryFunction, String alias) { QueryBuilder queryBuilderSubQuery = subQueryFunction.apply(new QueryBuilder(entityManager)); return this.from(queryBuilderSubQuery, alias); } @@ -98,30 +104,92 @@ private QueryBuilder join(String target, JoinType type) { return this; } + private QueryBuilder join(String target, String alias, String condition, JoinType type) { + String joinTargetWithAlias = StringUtils.isNotBlank(alias) + ? target.concat(" ").concat(alias) + : target; + String finalTarget = StringUtils.isNotBlank(condition) + ? joinTargetWithAlias.concat(" ON ").concat(condition) + : joinTargetWithAlias; + return this.join(finalTarget, type); + } + + private QueryBuilder join(Class target, String alias, String condition, JoinType type) { + return this.join(target.getSimpleName(), alias, condition, type); + } + + public QueryBuilder join(Class joinClass, String alias, String condition) { + return this.join(joinClass, alias, condition, JoinType.INNER); + } + + public QueryBuilder join(Class joinClass, String alias) { + return this.join(joinClass, alias, null); + } + public QueryBuilder join(String target, String condition) { - return this.join(target.concat(" ON ").concat(condition), JoinType.INNER); + return this.join(target, null, condition, JoinType.INNER); } public QueryBuilder join(String target) { return this.join(target, JoinType.INNER); } + public QueryBuilder joinFetch(Class joinClass, String alias, String condition) { + return this.join(joinClass, alias, condition, JoinType.INNER_FETCH); + } + + public QueryBuilder joinFetch(Class joinClass, String alias) { + return this.joinFetch(joinClass, alias, null); + } + public QueryBuilder joinFetch(String target) { return this.join(target, JoinType.INNER_FETCH); } + public QueryBuilder leftJoin(Class joinClass, String alias, String condition) { + return this.join(joinClass, alias, condition, JoinType.LEFT); + } + + public QueryBuilder leftJoin(Class joinClass, String alias) { + return this.leftJoin(joinClass, alias, null); + } + public QueryBuilder leftJoin(String target) { return this.join(target, JoinType.LEFT); } + public QueryBuilder leftJoinFetch(Class joinClass, String alias, String condition) { + return this.join(joinClass, alias, condition, JoinType.LEFT_FETCH); + } + + public QueryBuilder leftJoinFetch(Class joinClass, String alias) { + return this.leftJoinFetch(joinClass, alias, null); + } + public QueryBuilder leftJoinFetch(String target) { return this.join(target, JoinType.LEFT_FETCH); } + public QueryBuilder rightJoin(Class joinClass, String alias, String condition) { + return this.join(joinClass, alias, condition, JoinType.RIGHT); + } + + public QueryBuilder rightJoin(Class joinClass, String alias) { + return this.rightJoin(joinClass, alias, null); + } + public QueryBuilder rightJoin(String target) { return this.join(target, JoinType.RIGHT); } + public QueryBuilder rightJoinFetch(Class joinClass, String alias, String condition) { + return this.join(joinClass, alias, condition, JoinType.RIGHT_FETCH); + } + + public QueryBuilder rightJoinFetch(Class joinClass, String alias) { + return this.rightJoinFetch(joinClass, alias, null); + } + public QueryBuilder rightJoinFetch(String target) { return this.join(target, JoinType.RIGHT_FETCH); } @@ -149,6 +217,10 @@ public QueryBuilder whereIf(String clause, Object parameter, boolean shouldAddWh return shouldAddWhere ? this.where(clause, parameter) : this; } + public QueryBuilder whereNotIf(String clause, Object parameter, boolean shouldAddWhere) { + return this.whereIf(clause, parameter, !shouldAddWhere); + } + public QueryBuilder where(String clause) { return this.where(clause, (Object) null); } @@ -157,6 +229,10 @@ public QueryBuilder whereIf(String clause, boolean shouldAddWhere) { return shouldAddWhere ? this.where(clause) : this; } + public QueryBuilder whereNotIf(String clause, boolean shouldAddWhere) { + return this.whereIf(clause, !shouldAddWhere); + } + public QueryBuilder or() { this.lastOperator = QueryOperator.OR; return this; @@ -184,17 +260,21 @@ public QueryBuilder orderBy(String orderBy) { return this; } - public QueryBuilder addOrderBy(String orderBy) { - this.orderBy.addOrderBy(orderBy); + public QueryBuilder orderBy(String orderBy, SortDirection sortDirection) { + if (Objects.nonNull(this.orderBy)) { + this.orderBy.addOrderBy(orderBy, sortDirection); + } else { + this.orderBy = new OrderBy(orderBy, sortDirection); + } return this; } - public QueryBuilder firstResult(Integer firstResult) { + public QueryBuilder firstResult(int firstResult) { this.firstResult = firstResult; return this; } - public QueryBuilder maxResults(Integer maxResults) { + public QueryBuilder maxResults(int maxResults) { this.maxResults = maxResults; return this; } @@ -236,6 +316,8 @@ public String getQueryString() { } public TypedQuery getQuery(Class resultClass) { + Objects.requireNonNull(entityManager, "It is not allowed to execute a query without inject a entity manager"); + String queryString = this.getQueryString(); TypedQuery query = this.entityManager.createQuery(queryString, resultClass) .setFirstResult(firstResult) @@ -245,6 +327,8 @@ public TypedQuery getQuery(Class resultClass) { } public Query getNativeQuery() { + Objects.requireNonNull(entityManager, "It is not allowed to execute a query without inject a entity manager"); + String queryString = this.getQueryString(); Query query = this.entityManager.createNativeQuery(queryString, Tuple.class) .setFirstResult(firstResult) diff --git a/src/main/java/io/github/andersoncrocha/jpqlquerybuilder/operations/OrderBy.java b/src/main/java/io/github/andersoncrocha/jpqlquerybuilder/operations/OrderBy.java index 1ffdba0..3058937 100644 --- a/src/main/java/io/github/andersoncrocha/jpqlquerybuilder/operations/OrderBy.java +++ b/src/main/java/io/github/andersoncrocha/jpqlquerybuilder/operations/OrderBy.java @@ -1,35 +1,52 @@ package io.github.andersoncrocha.jpqlquerybuilder.operations; -import java.util.Objects; -import java.util.Set; +import io.github.andersoncrocha.jpqlquerybuilder.operations.types.SortDirection; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; public class OrderBy implements QueryOperation { - private final Set fields; + private final Map fields; public OrderBy(String fields) { this.fields = this.prepareFields(fields); } + public OrderBy(String field, SortDirection sortDirection) { + this.fields = new HashMap<>(); + this.fields.put(field, sortDirection); + } + public void addOrderBy(String fields) { - Objects.requireNonNull(fields, "addOrderBy() cannot be called before orderBy() method"); - Set preparedFields = this.prepareFields(fields); - this.fields.addAll(preparedFields); + Map preparedFields = this.prepareFields(fields); + this.fields.putAll(preparedFields); + } + + public void addOrderBy(String field, SortDirection sortDirection) { + this.fields.put(field, sortDirection); } @Override public String getOperation() { - String joinedFields = String.join(", ", this.fields); + String joinedFields = this.fields.entrySet() + .stream() + .map(entry -> { + String field = entry.getKey(); + SortDirection sortDirection = entry.getValue(); + return String.format("%s %s", field, sortDirection.name()); + }).collect(Collectors.joining(", ")); return String.format("ORDER BY %s ", joinedFields); } - private Set prepareFields(String fields) { + private Map prepareFields(String fields) { String[] separatedFields = fields.split(","); return Stream.of(separatedFields) .map(String::trim) - .collect(Collectors.toSet()); + .collect(Collectors.toMap(Function.identity(), field -> SortDirection.ASC)); } } diff --git a/src/main/java/io/github/andersoncrocha/jpqlquerybuilder/operations/types/SortDirection.java b/src/main/java/io/github/andersoncrocha/jpqlquerybuilder/operations/types/SortDirection.java new file mode 100644 index 0000000..454bac2 --- /dev/null +++ b/src/main/java/io/github/andersoncrocha/jpqlquerybuilder/operations/types/SortDirection.java @@ -0,0 +1,12 @@ +package io.github.andersoncrocha.jpqlquerybuilder.operations.types; + +public enum SortDirection { + + ASC, + DESC; + + public static SortDirection isAscending(boolean isAscending) { + return isAscending ? ASC : DESC; + } + +}