refactor(service): 将查询条件解析逻辑封装到 QueryParser 中
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
package com.lanyuanxiaoyao.service.template.jpa.controller;
|
||||
|
||||
import com.lanyuanxiaoyao.service.template.common.controller.GlobalResponse;
|
||||
import com.lanyuanxiaoyao.service.template.common.controller.Query;
|
||||
import com.lanyuanxiaoyao.service.template.common.controller.SimpleController;
|
||||
import com.lanyuanxiaoyao.service.template.common.entity.GlobalResponse;
|
||||
import com.lanyuanxiaoyao.service.template.common.entity.Query;
|
||||
import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper;
|
||||
import com.lanyuanxiaoyao.service.template.jpa.entity.SimpleEntity;
|
||||
import com.lanyuanxiaoyao.service.template.jpa.service.SimpleServiceSupport;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package com.lanyuanxiaoyao.service.template.jpa.service;
|
||||
|
||||
import com.lanyuanxiaoyao.service.template.common.controller.Query;
|
||||
import com.lanyuanxiaoyao.service.template.common.entity.Page;
|
||||
import com.lanyuanxiaoyao.service.template.common.entity.Query;
|
||||
import com.lanyuanxiaoyao.service.template.common.exception.IdNotFoundException;
|
||||
import com.lanyuanxiaoyao.service.template.common.exception.NotCollectionException;
|
||||
import com.lanyuanxiaoyao.service.template.common.exception.NotComparableException;
|
||||
import com.lanyuanxiaoyao.service.template.common.exception.NotStringException;
|
||||
import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper;
|
||||
import com.lanyuanxiaoyao.service.template.common.service.Page;
|
||||
import com.lanyuanxiaoyao.service.template.common.service.QueryParser;
|
||||
import com.lanyuanxiaoyao.service.template.common.service.SimpleService;
|
||||
import com.lanyuanxiaoyao.service.template.jpa.entity.IdOnlyEntity;
|
||||
import com.lanyuanxiaoyao.service.template.jpa.entity.SimpleEntity;
|
||||
@@ -159,300 +160,6 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析字段路径
|
||||
* <p>
|
||||
* 支持多级字段路径解析,使用"."分隔多级字段。
|
||||
* 例如: "user.name" 表示实体的user属性的name字段。
|
||||
* </p>
|
||||
*
|
||||
* @param root JPA Criteria查询根节点
|
||||
* @param column 字段路径字符串
|
||||
* @param <Y> 字段类型
|
||||
* @return 返回字段路径对象
|
||||
* @throws IllegalArgumentException 当字段路径为空时抛出
|
||||
*/
|
||||
private <Y> Path<Y> column(Root<ENTITY> root, String column) {
|
||||
if (ObjectHelper.isEmpty(column)) {
|
||||
throw new IllegalArgumentException("Column cannot be blank");
|
||||
}
|
||||
var columns = column.split("\\.");
|
||||
Path<Y> path = root.get(columns[0]);
|
||||
for (int i = 1; i < columns.length; i++) {
|
||||
path = path.get(columns[i]);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理字段值
|
||||
* <p>
|
||||
* 对于枚举类型字段,将字符串值转换为对应的枚举值。
|
||||
* 对于LocalDateTime类型字段,将字符串转换为时间对象。
|
||||
* 其他类型直接返回原值。
|
||||
* </p>
|
||||
*
|
||||
* @param column 字段路径
|
||||
* @param value 字段值
|
||||
* @param <Y> 字段类型
|
||||
* @return 处理后的字段值
|
||||
* @throws IllegalArgumentException 当枚举类型字段的值不是字符串时抛出
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private <Y> Object value(Path<Y> column, Object value) {
|
||||
if (ObjectHelper.isNull(value)) {
|
||||
return null;
|
||||
}
|
||||
var javaType = column.getJavaType();
|
||||
if (javaType.isEnum()) {
|
||||
if (value instanceof String enumName) {
|
||||
var enumType = (Class<Enum>) javaType;
|
||||
return Enum.valueOf(enumType, enumName);
|
||||
} else {
|
||||
throw new IllegalArgumentException("枚举类型字段需要 String 类型的值");
|
||||
}
|
||||
} else if (javaType.isAssignableFrom(LocalDateTime.class)) {
|
||||
return LocalDateTime.parse(String.valueOf(value), DATE_TIME_FORMATTER);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询条件谓词列表
|
||||
* <p>
|
||||
* 根据Query.Queryable对象构建JPA Criteria查询的谓词列表。
|
||||
* 支持多种查询条件类型,包括相等、不等、模糊匹配、范围查询等。
|
||||
* </p>
|
||||
*
|
||||
* @param queryable 查询条件对象
|
||||
* @param root JPA Criteria查询根节点
|
||||
* @param query JPA Criteria查询对象
|
||||
* @param builder JPA Criteria构建器
|
||||
* @return 返回构建的谓词列表
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Predicate queryPredicates(Query.Queryable queryable, Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
||||
var predicates = new ArrayList<Predicate>();
|
||||
if (ObjectHelper.isNull(queryable)) {
|
||||
return null;
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.nullEqual())) {
|
||||
queryable.nullEqual().forEach(column -> predicates.add(builder.isNull(column(root, column))));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.notNullEqual())) {
|
||||
queryable.notNullEqual().forEach(column -> predicates.add(builder.isNotNull(column(root, column))));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.empty())) {
|
||||
queryable.empty().forEach(column -> {
|
||||
var path = this.<Collection<Object>>column(root, column);
|
||||
checkCollection(path, column);
|
||||
predicates.add(builder.isEmpty(path));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.notEmpty())) {
|
||||
queryable.notEmpty().forEach(column -> {
|
||||
var path = this.<Collection<Object>>column(root, column);
|
||||
checkCollection(path, column);
|
||||
predicates.add(builder.isNotEmpty(path));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.equal())) {
|
||||
queryable.equal().forEach((column, value) -> {
|
||||
var path = column(root, column);
|
||||
predicates.add(builder.equal(path, value(path, value)));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.notEqual())) {
|
||||
queryable.notEqual().forEach((column, value) -> {
|
||||
var path = column(root, column);
|
||||
predicates.add(builder.notEqual(path, value(path, value)));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.like())) {
|
||||
queryable.like().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.like(path, value));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.notLike())) {
|
||||
queryable.notLike().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.notLike(path, value));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.contain())) {
|
||||
queryable.contain().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.like(path, "%" + value + "%"));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.notContain())) {
|
||||
queryable.notContain().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.notLike(path, "%" + value + "%"));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.startWith())) {
|
||||
queryable.startWith().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.like(path, value + "%"));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.notStartWith())) {
|
||||
queryable.notStartWith().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.notLike(path, value + "%"));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.endWith())) {
|
||||
queryable.endWith().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.like(path, "%" + value));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.notEndWith())) {
|
||||
queryable.notEndWith().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.notLike(path, "%" + value));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.great())) {
|
||||
queryable.great().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.greaterThan(path, (Comparable<Object>) value(path, value)));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.less())) {
|
||||
queryable.less().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.lessThan(path, (Comparable<Object>) value(path, value)));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.greatEqual())) {
|
||||
queryable.greatEqual().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.greaterThanOrEqualTo(path, (Comparable<Object>) value(path, value)));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.lessEqual())) {
|
||||
queryable.lessEqual().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.lessThanOrEqualTo(path, (Comparable<Object>) value(path, value)));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.inside())) {
|
||||
queryable.inside()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> ObjectHelper.isNotEmpty(entry.getValue()))
|
||||
.forEach(entry -> predicates.add(builder.in(column(root, entry.getKey())).value(entry.getValue())));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.notInside())) {
|
||||
queryable.notInside()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> ObjectHelper.isNotEmpty(entry.getValue()))
|
||||
.forEach(entry -> predicates.add(builder.in(column(root, entry.getKey())).value(entry.getValue()).not()));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.between())) {
|
||||
queryable.between().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.between(path, (Comparable<Object>) value(path, value.start()), (Comparable<Object>) value(path, value.end())));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.notBetween())) {
|
||||
queryable.notBetween().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.between(path, (Comparable<Object>) value(path, value.start()), (Comparable<Object>) value(path, value.end())).not());
|
||||
});
|
||||
}
|
||||
|
||||
return predicates.size() == 1
|
||||
? predicates.get(0)
|
||||
: builder.and(predicates.toArray(Predicate[]::new));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查字段类型是否可比较
|
||||
*
|
||||
* @param path 字段路径
|
||||
* @param value 比较值
|
||||
* @param column 字段名称
|
||||
* @throws NotComparableException 当字段类型不可比较时抛出
|
||||
*/
|
||||
private void checkComparable(Path<?> path, Object value, String column) {
|
||||
if (!ObjectHelper.isComparable(path.getJavaType()) || !ObjectHelper.isComparable(value)) {
|
||||
throw new NotComparableException(column);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查区间值是否可比较
|
||||
*
|
||||
* @param path 字段路径
|
||||
* @param value 区间对象
|
||||
* @param column 字段名称
|
||||
* @throws NotComparableException 当区间值不可比较时抛出
|
||||
*/
|
||||
private void checkComparable(Path<?> path, Query.Queryable.Between value, String column) {
|
||||
checkComparable(path, value.start(), column);
|
||||
checkComparable(path, value.end(), column);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查字段类型是否为集合
|
||||
*
|
||||
* @param path 字段路径
|
||||
* @param column 字段名称
|
||||
* @throws NotCollectionException 当字段类型不是集合时抛出
|
||||
*/
|
||||
private void checkCollection(Path<?> path, String column) {
|
||||
if (!ObjectHelper.isCollection(path.getJavaType())) {
|
||||
throw new NotCollectionException(column);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查值是否为集合
|
||||
*
|
||||
* @param value 值对象
|
||||
* @param column 字段名称
|
||||
* @throws NotCollectionException 当值不是集合时抛出
|
||||
*/
|
||||
private void checkCollection(Object value, String column) {
|
||||
if (!ObjectHelper.isCollection(value)) {
|
||||
throw new NotCollectionException(column);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查字段类型是否为字符串
|
||||
*
|
||||
* @param path 字段路径
|
||||
* @param value 比较值
|
||||
* @param column 字段名称
|
||||
* @throws NotStringException 当字段类型不是字符串时抛出
|
||||
*/
|
||||
private void checkString(Path<?> path, Object value, String column) {
|
||||
if (!ObjectHelper.isString(path.getJavaType()) || !ObjectHelper.isString(value)) {
|
||||
throw new NotStringException(column);
|
||||
}
|
||||
}
|
||||
|
||||
protected Predicate commonPredicates(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
||||
return null;
|
||||
}
|
||||
@@ -487,7 +194,7 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
||||
var result = repository.findAll(
|
||||
(root, query, builder) -> {
|
||||
var predicate = commonPredicates(root, query, builder);
|
||||
var queryPredicate = queryPredicates(listQuery.query(), root, query, builder);
|
||||
var queryPredicate = new JpaQueryParser<>(root, query, builder).build(listQuery.query());
|
||||
return ObjectHelper.isNull(predicate)
|
||||
? queryPredicate
|
||||
: builder.and(predicate, queryPredicate);
|
||||
@@ -586,4 +293,339 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
||||
repository.deleteBatchByIds(ids);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final class JpaQueryParser<ENTITY> extends QueryParser<Predicate> {
|
||||
private final Root<ENTITY> root;
|
||||
@SuppressWarnings({"unused", "FieldCanBeLocal"})
|
||||
private final CriteriaQuery<?> query;
|
||||
private final CriteriaBuilder builder;
|
||||
private final List<Predicate> predicates = new ArrayList<>();
|
||||
|
||||
private JpaQueryParser(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
||||
this.root = root;
|
||||
this.query = query;
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析字段路径
|
||||
* <p>
|
||||
* 支持多级字段路径解析,使用"."分隔多级字段。
|
||||
* 例如: "user.name" 表示实体的user属性的name字段。
|
||||
* </p>
|
||||
*
|
||||
* @param root JPA Criteria查询根节点
|
||||
* @param column 字段路径字符串
|
||||
* @param <Y> 字段类型
|
||||
* @return 返回字段路径对象
|
||||
* @throws IllegalArgumentException 当字段路径为空时抛出
|
||||
*/
|
||||
private <Y> Path<Y> column(Root<ENTITY> root, String column) {
|
||||
if (ObjectHelper.isEmpty(column)) {
|
||||
throw new IllegalArgumentException("Column cannot be blank");
|
||||
}
|
||||
var columns = column.split("\\.");
|
||||
Path<Y> path = root.get(columns[0]);
|
||||
for (int i = 1; i < columns.length; i++) {
|
||||
path = path.get(columns[i]);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理字段值
|
||||
* <p>
|
||||
* 对于枚举类型字段,将字符串值转换为对应的枚举值。
|
||||
* 对于LocalDateTime类型字段,将字符串转换为时间对象。
|
||||
* 其他类型直接返回原值。
|
||||
* </p>
|
||||
*
|
||||
* @param column 字段路径
|
||||
* @param value 字段值
|
||||
* @param <Y> 字段类型
|
||||
* @return 处理后的字段值
|
||||
* @throws IllegalArgumentException 当枚举类型字段的值不是字符串时抛出
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private <Y> Object value(Path<Y> column, Object value) {
|
||||
if (ObjectHelper.isNull(value)) {
|
||||
return null;
|
||||
}
|
||||
var javaType = column.getJavaType();
|
||||
if (javaType.isEnum()) {
|
||||
if (value instanceof String enumName) {
|
||||
var enumType = (Class<Enum>) javaType;
|
||||
return Enum.valueOf(enumType, enumName);
|
||||
} else {
|
||||
throw new IllegalArgumentException("枚举类型字段需要 String 类型的值");
|
||||
}
|
||||
} else if (javaType.isAssignableFrom(LocalDateTime.class)) {
|
||||
return LocalDateTime.parse(String.valueOf(value), DATE_TIME_FORMATTER);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查字段类型是否可比较
|
||||
*
|
||||
* @param path 字段路径
|
||||
* @param value 比较值
|
||||
* @param column 字段名称
|
||||
* @throws NotComparableException 当字段类型不可比较时抛出
|
||||
*/
|
||||
private void checkComparable(Path<?> path, Object value, String column) {
|
||||
if (!ObjectHelper.isComparable(path.getJavaType()) || !ObjectHelper.isComparable(value)) {
|
||||
throw new NotComparableException(column);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查区间值是否可比较
|
||||
*
|
||||
* @param path 字段路径
|
||||
* @param value 区间对象
|
||||
* @param column 字段名称
|
||||
* @throws NotComparableException 当区间值不可比较时抛出
|
||||
*/
|
||||
private void checkComparable(Path<?> path, Query.Queryable.Between value, String column) {
|
||||
checkComparable(path, value.start(), column);
|
||||
checkComparable(path, value.end(), column);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查字段类型是否为集合
|
||||
*
|
||||
* @param path 字段路径
|
||||
* @param column 字段名称
|
||||
* @throws NotCollectionException 当字段类型不是集合时抛出
|
||||
*/
|
||||
private void checkCollection(Path<?> path, String column) {
|
||||
if (!ObjectHelper.isCollection(path.getJavaType())) {
|
||||
throw new NotCollectionException(column);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查值是否为集合
|
||||
*
|
||||
* @param value 值对象
|
||||
* @param column 字段名称
|
||||
* @throws NotCollectionException 当值不是集合时抛出
|
||||
*/
|
||||
private void checkCollection(Object value, String column) {
|
||||
if (!ObjectHelper.isCollection(value)) {
|
||||
throw new NotCollectionException(column);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查字段类型是否为字符串
|
||||
*
|
||||
* @param path 字段路径
|
||||
* @param value 比较值
|
||||
* @param column 字段名称
|
||||
* @throws NotStringException 当字段类型不是字符串时抛出
|
||||
*/
|
||||
private void checkString(Path<?> path, Object value, String column) {
|
||||
if (!ObjectHelper.isString(path.getJavaType()) || !ObjectHelper.isString(value)) {
|
||||
throw new NotStringException(column);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void nullEqual(Query.Queryable queryable) {
|
||||
queryable.nullEqual().forEach(column -> predicates.add(builder.isNull(column(root, column))));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notNullEqual(Query.Queryable queryable) {
|
||||
queryable.notNullEqual().forEach(column -> predicates.add(builder.isNotNull(column(root, column))));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void empty(Query.Queryable queryable) {
|
||||
queryable.empty().forEach(column -> {
|
||||
var path = this.<Collection<Object>>column(root, column);
|
||||
checkCollection(path, column);
|
||||
predicates.add(builder.isEmpty(path));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notEmpty(Query.Queryable queryable) {
|
||||
queryable.notEmpty().forEach(column -> {
|
||||
var path = this.<Collection<Object>>column(root, column);
|
||||
checkCollection(path, column);
|
||||
predicates.add(builder.isNotEmpty(path));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void equal(Query.Queryable queryable) {
|
||||
queryable.equal().forEach((column, value) -> {
|
||||
var path = column(root, column);
|
||||
predicates.add(builder.equal(path, value(path, value)));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notEqual(Query.Queryable queryable) {
|
||||
queryable.notEqual().forEach((column, value) -> {
|
||||
var path = column(root, column);
|
||||
predicates.add(builder.notEqual(path, value(path, value)));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void like(Query.Queryable queryable) {
|
||||
queryable.like().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.like(path, value));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notLike(Query.Queryable queryable) {
|
||||
queryable.notLike().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.notLike(path, value));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contain(Query.Queryable queryable) {
|
||||
queryable.contain().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.like(path, "%" + value + "%"));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notContain(Query.Queryable queryable) {
|
||||
queryable.notContain().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.notLike(path, "%" + value + "%"));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startWith(Query.Queryable queryable) {
|
||||
queryable.startWith().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.like(path, value + "%"));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notStartWith(Query.Queryable queryable) {
|
||||
queryable.notStartWith().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.notLike(path, value + "%"));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void endWith(Query.Queryable queryable) {
|
||||
queryable.endWith().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.like(path, "%" + value));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notEndWith(Query.Queryable queryable) {
|
||||
queryable.notEndWith().forEach((column, value) -> {
|
||||
var path = this.<String>column(root, column);
|
||||
checkString(path, value, column);
|
||||
predicates.add(builder.notLike(path, "%" + value));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void great(Query.Queryable queryable) {
|
||||
queryable.great().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.greaterThan(path, (Comparable<Object>) value(path, value)));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void less(Query.Queryable queryable) {
|
||||
queryable.less().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.lessThan(path, (Comparable<Object>) value(path, value)));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void greatEqual(Query.Queryable queryable) {
|
||||
queryable.greatEqual().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.greaterThanOrEqualTo(path, (Comparable<Object>) value(path, value)));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void lessEqual(Query.Queryable queryable) {
|
||||
queryable.lessEqual().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.lessThanOrEqualTo(path, (Comparable<Object>) value(path, value)));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inside(Query.Queryable queryable) {
|
||||
queryable.inside()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> ObjectHelper.isNotEmpty(entry.getValue()))
|
||||
.forEach(entry -> predicates.add(builder.in(column(root, entry.getKey())).value(entry.getValue())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notInside(Query.Queryable queryable) {
|
||||
queryable.notInside()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> ObjectHelper.isNotEmpty(entry.getValue()))
|
||||
.forEach(entry -> predicates.add(builder.in(column(root, entry.getKey())).value(entry.getValue()).not()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void between(Query.Queryable queryable) {
|
||||
queryable.between().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.between(path, (Comparable<Object>) value(path, value.start()), (Comparable<Object>) value(path, value.end())));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notBetween(Query.Queryable queryable) {
|
||||
queryable.notBetween().forEach((column, value) -> {
|
||||
var path = this.<Comparable<Object>>column(root, column);
|
||||
checkComparable(path, value, column);
|
||||
predicates.add(builder.between(path, (Comparable<Object>) value(path, value.start()), (Comparable<Object>) value(path, value.end())).not());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Predicate build() {
|
||||
return predicates.size() == 1
|
||||
? predicates.get(0)
|
||||
: builder.and(predicates.toArray(Predicate[]::new));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user