package org.dayatang.domain;
import org.apache.commons.lang3.StringUtils;
import org.dayatang.utils.Assert;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* 条件查询。DDDLib支持的四种查询形式之一。 通过DSL针对特定实体指定查询条件、排序属性和针对结果取子集等。 Created with
* IntelliJ IDEA. User: yyang Date: 13-10-17 Time: 下午2:14 To change this
* template use File | Settings | File Templates.
*/
public class CriteriaQuery {
private final EntityRepository repository;
private final Class<? extends Entity> entityClass;
private int firstResult;
private int maxResults;
private QueryCriterion criterion = Criteria.empty();
private final OrderSettings orderSettings = new OrderSettings();
public CriteriaQuery(EntityRepository repository, Class<? extends Entity> entityClass) {
Assert.notNull(repository);
Assert.notNull(entityClass);
this.repository = repository;
this.entityClass = entityClass;
}
/**
* 获得查询根实体的类
*
* @return 查询的根实体的类
*/
public Class getEntityClass() {
return entityClass;
}
/**
* 对于从大结果集中选取部分的查询,获得数据集的起始位置(0代表第一条记录)
*
* @return 一个数字,代表从大结果集的第几条记录开始选取子集
*/
public int getFirstResult() {
return firstResult;
}
/**
* 对于从大结果集中选取部分的查询,设置数据集的起始获取位置(0代表第一条记录)
*
* @param firstResult 一个数字,代表从大结果集的第几条记录开始选取子集
* @return 当前查询对象
*/
public CriteriaQuery setFirstResult(int firstResult) {
this.firstResult = firstResult;
return this;
}
/**
* 对于从大结果集中选取部分的查询,获得本次查询返回的记录的最大数量
*
* @return 一个数字,代表从大数据集中最多选取多少条记录
*/
public int getMaxResults() {
return maxResults;
}
/**
* 对于从大结果集中选取部分的查询,获得本次查询返回的记录的最大数量
*
* @param maxResults 一个数字,代表从大数据集中最多选取多少条记录
* @return 当前查询对象
*/
public CriteriaQuery setMaxResults(int maxResults) {
this.maxResults = maxResults;
return this;
}
/**
* 获得查询条件
*
* @return 本次查询指定的查询条件
*/
public QueryCriterion getQueryCriterion() {
return criterion;
}
/**
* 获得排序选项
*
* @return 本次查询指定的排序选项
*/
public OrderSettings getOrderSettings() {
return orderSettings;
}
/**
* 获得JPQL查询字符串
*
* @return 该查询对应的JPQL查询字符串
*/
public String getQueryString() {
String result = String.format("select distinct(%s) from %s as %s ",
QueryCriterion.ROOT_ALIAS, entityClass.getName(), QueryCriterion.ROOT_ALIAS);
if (StringUtils.isNotEmpty(criterion.toQueryString())) {
result += " where " + criterion.toQueryString();
}
result += getOrderClause();
return result;
}
private String getOrderClause() {
List<KeyValue<String, Boolean>> orderBy = orderSettings.getOrderBy();
if (orderBy.isEmpty()) {
return "";
}
List<String> elements = new ArrayList<String>();
for (KeyValue<String, Boolean> each : orderBy) {
elements.add(QueryCriterion.ROOT_ALIAS + "." + each.getKey() + (each.getValue().booleanValue() ? " asc" : " desc"));
}
return " order by " + StringUtils.join(elements, ", ");
}
/**
* 获取查询参数
*
* @return 查询参数
*/
public NamedParameters getParameters() {
return criterion.getParameters();
}
/**
* 添加一个“属性名 = 属性值”的查询条件
*
* @param propName 属性名
* @param value 属性值
* @return 当前查询对象
*/
public CriteriaQuery eq(String propName, Object value) {
criterion = criterion.and(Criteria.eq(propName, value));
return this;
}
/**
* 添加一个“属性名 != 属性值”的查询条件
*
* @param propName 属性名
* @param value 属性值
* @return 当前查询对象
*/
public CriteriaQuery notEq(String propName, Object value) {
criterion = criterion.and(Criteria.notEq(propName, value));
return this;
}
/**
* 添加一个“属性名 大于 属性值”的查询条件
*
* @param propName 属性名
* @param value 属性值
* @return 当前查询对象
*/
public CriteriaQuery gt(String propName, Comparable<?> value) {
criterion = criterion.and(Criteria.gt(propName, value));
return this;
}
/**
* 添加一个“属性名 大于或等于 属性值”的查询条件
*
* @param propName 属性名
* @param value 属性值
* @return 当前查询对象
*/
public CriteriaQuery ge(String propName, Comparable<?> value) {
criterion = criterion.and(Criteria.ge(propName, value));
return this;
}
/**
* 添加一个“属性名 小于 属性值”的查询条件
* @param propName 属性名
* @param value 属性值
* @return 当前查询对象
*/
public CriteriaQuery lt(String propName, Comparable<?> value) {
criterion = criterion.and(Criteria.lt(propName, value));
return this;
}
/**
* 添加一个“属性名 小于或等于 属性值”的查询条件
* @param propName 属性名
* @param value 属性值
* @return 当前查询对象
*/
public CriteriaQuery le(String propName, Comparable<?> value) {
criterion = criterion.and(Criteria.le(propName, value));
return this;
}
/**
* 添加一个“属性1 等于 属性2”的查询条件
*
* @param propName 属性名
* @param otherProp 另一个属性名
* @return 当前查询对象
*/
public CriteriaQuery eqProp(String propName, String otherProp) {
criterion = criterion.and(Criteria.eqProp(propName, otherProp));
return this;
}
/**
* 添加一个“属性1 不等于 属性2”的查询条件
*
* @param propName 属性名
* @param otherProp 另一个属性名
* @return 当前查询对象
*/
public CriteriaQuery notEqProp(String propName, String otherProp) {
criterion = criterion.and(Criteria.notEqProp(propName, otherProp));
return this;
}
/**
* 添加一个“属性1 大于 属性2”的查询条件
*
* @param propName 属性名
* @param otherProp 另一个属性名
* @return 当前查询对象
*/
public CriteriaQuery gtProp(String propName, String otherProp) {
criterion = criterion.and(Criteria.gtProp(propName, otherProp));
return this;
}
/**
* 添加一个“属性1 大于或等于 属性2”的查询条件
*
* @param propName 属性名
* @param otherProp 另一个属性名
* @return 当前查询对象
*/
public CriteriaQuery geProp(String propName, String otherProp) {
criterion = criterion.and(Criteria.geProp(propName, otherProp));
return this;
}
/**
* 添加一个“属性1 小于 属性2”的查询条件
* @param propName 属性名
* @param otherProp 另一个属性名
* @return 当前查询对象
*/
public CriteriaQuery ltProp(String propName, String otherProp) {
criterion = criterion.and(Criteria.ltProp(propName, otherProp));
return this;
}
/**
* 添加一个“属性1 小于或等于 属性2”的查询条件
* @param propName 属性名
* @param otherProp 另一个属性名
* @return 当前查询对象
*/
public CriteriaQuery leProp(String propName, String otherProp) {
criterion = criterion.and(Criteria.leProp(propName, otherProp));
return this;
}
/**
* 添加一个“集合属性的结果数量 等于 size”的查询条件。例如Order对象有个类型为List<OrderItem>的
* 集合属性items,我们要查询订购了5种物品的订单,则propName为items,size为5.
*
* @param propName 属性名,必须是集合属性(x-to-many或ElementCollection)
* @param size 集合属性的结果数量
* @return 当前查询对象
*/
public CriteriaQuery sizeEq(String propName, int size) {
criterion = criterion.and(Criteria.sizeEq(propName, size));
return this;
}
/**
* 添加一个“集合属性的结果数量 不等于 size”的查询条件。例如Order对象有个类型为List<OrderItem>的
* 集合属性items,我们要查询订购了不是5种物品的订单,则propName为items,size为5.
*
* @param propName 属性名,必须是集合属性(x-to-many或ElementCollection)
* @param size 集合属性的结果数量
* @return 当前查询对象
*/
public CriteriaQuery sizeNotEq(String propName, int size) {
criterion = criterion.and(Criteria.sizeNotEq(propName, size));
return this;
}
/**
* 添加一个“集合属性的结果数量 大于 size”的查询条件。例如Order对象有个类型为List<OrderItem>的
* 集合属性items,我们要查询订购了超过5种物品的订单,则propName为items,size为5.
*
* @param propName 属性名,必须是集合属性(x-to-many或ElementCollection)
* @param size 集合属性的结果数量
* @return 当前查询对象
*/
public CriteriaQuery sizeGt(String propName, int size) {
criterion = criterion.and(Criteria.sizeGt(propName, size));
return this;
}
/**
* 添加一个“集合属性的结果数量 大于或等于 size”的查询条件。例如Order对象有个类型为List<OrderItem>的
* 集合属性items,我们要查询订购了5种或5种以上物品的订单,则propName为items,size为5.
*
* @param propName 属性名,必须是集合属性(x-to-many或ElementCollection)
* @param size 集合属性的结果数量
* @return 当前查询对象
*/
public CriteriaQuery sizeGe(String propName, int size) {
criterion = criterion.and(Criteria.sizeGe(propName, size));
return this;
}
/**
* 添加一个“集合属性的结果数量 小于 size”的查询条件。例如Order对象有个类型为List<OrderItem>的
* 集合属性items,我们要查询订购了少于5种物品的订单,则propName为items,size为5.
*
* @param propName 属性名,必须是集合属性(x-to-many或ElementCollection)
* @param size 集合属性的结果数量
* @return 当前查询对象
*/
public CriteriaQuery sizeLt(String propName, int size) {
criterion = criterion.and(Criteria.sizeLt(propName, size));
return this;
}
/**
* 添加一个“集合属性的结果数量 小于或等于 size”的查询条件。例如Order对象有个类型为List<OrderItem>的
* 集合属性items,我们要查询订购了5种或5种以下物品的订单,则propName为items,size为5.
*
* @param propName 属性名,必须是集合属性(x-to-many或ElementCollection)
* @param size 集合属性的结果数量
* @return 当前查询对象
*/
public CriteriaQuery sizeLe(String propName, int size) {
criterion = criterion.and(Criteria.sizeLe(propName, size));
return this;
}
/**
* 添加一个“属性包含指定文本”的查询条件
*
* @param propName 属性名,该属性必须是字符串类型
* @param value 文本内容
* @return 当前查询对象
*/
public CriteriaQuery containsText(String propName, String value) {
criterion = criterion.and(Criteria.containsText(propName, value));
return this;
}
/**
* 添加一个“属性以指定文本开头”的查询条件
*
* @param propName 属性名,该属性必须是字符串类型
* @param value 文本内容
* @return 当前查询对象
*/
public CriteriaQuery startsWithText(String propName, String value) {
criterion = criterion.and(Criteria.startsWithText(propName, value));
return this;
}
/**
* 添加一个“属性值包含在指定的集合内”的查询条件
*
* @param propName 属性名
* @param value 一个集合,符合查询条件的属性值必须包含在该集合内
* @return 当前查询对象
*/
public CriteriaQuery in(String propName, Collection<? extends Object> value) {
criterion = criterion.and(Criteria.in(propName, value));
return this;
}
/**
* 添加一个“属性值包含在指定的数组内”的查询条件
*
* @param propName 属性名
* @param value 一个数组,符合查询条件的属性值必须包含在该数组内
* @return 当前查询对象
*/
public CriteriaQuery in(String propName, Object[] value) {
criterion = criterion.and(Criteria.in(propName, value));
return this;
}
/**
* 添加一个“属性值不包含在指定的集合内”的查询条件
*
* @param propName 属性名
* @param value 一个集合,符合查询条件的属性值必须不包含在该集合内
* @return 当前查询对象
*/
public CriteriaQuery notIn(String propName, Collection<? extends Object> value) {
criterion = criterion.and(Criteria.notIn(propName, value));
return this;
}
/**
* 添加一个“属性值不包含在指定的数组内”的查询条件
*
* @param propName 属性名
* @param value 一个数组,符合查询条件的属性值必须不包含在该数组内
* @return 当前查询对象
*/
public CriteriaQuery notIn(String propName, Object[] value) {
criterion = criterion.and(Criteria.notIn(propName, value));
return this;
}
/**
* 添加一个“属性值介于两个值之间(包含左右边界)”的查询条件
*
* @param propName 属性名
* @param from 第一个边界值
* @param to 第二个边界值
* @param <E> 被比较的值的类型,也就是属性的兼容类型
* @return 当前查询对象
*/
public <E> CriteriaQuery between(String propName, Comparable<E> from, Comparable<E> to) {
criterion = criterion.and(Criteria.between(propName, from, to));
return this;
}
/**
* 添加一个“属性值是Null”的查询条件
*
* @param propName 属性名
* @return 当前查询对象
*/
public CriteriaQuery isNull(String propName) {
criterion = criterion.and(Criteria.isNull(propName));
return this;
}
/**
* 添加一个“属性值不是Null”的查询条件
*
* @param propName 属性名
* @return 当前查询对象
*/
public CriteriaQuery notNull(String propName) {
criterion = criterion.and(Criteria.notNull(propName));
return this;
}
/**
* 添加一个“集合类型属性值为空集合”的查询条件
*
* @param propName 属性名,必须是集合属性(x-to-many或ElementCollection)
* @return 当前查询对象
*/
public CriteriaQuery isEmpty(String propName) {
criterion = criterion.and(Criteria.isEmpty(propName));
return this;
}
/**
* 添加一个“集合类型属性值不是空集合”的查询条件
*
* @param propName 属性名,必须是集合属性(x-to-many或ElementCollection)
* @return 当前查询对象
*/
public CriteriaQuery notEmpty(String propName) {
criterion = criterion.and(Criteria.notEmpty(propName));
return this;
}
/**
* 添加一个“属性值为true”的查询条件
*
* @param propName 属性名
* @return 当前查询对象
*/
public CriteriaQuery isTrue(String propName) {
criterion = criterion.and(Criteria.isTrue(propName));
return this;
}
/**
* 添加一个“属性值为false”的查询条件
*
* @param propName 属性名
* @return 当前查询对象
*/
public CriteriaQuery isFalse(String propName) {
criterion = criterion.and(Criteria.isFalse(propName));
return this;
}
/**
* 添加一个“属性值为空白,即Null或空字符串”的查询条件
*
* @param propName 属性名,必须是字符串型属性
* @return 当前查询对象
*/
public CriteriaQuery isBlank(String propName) {
criterion = criterion.and(Criteria.isBlank(propName));
return this;
}
/**
* 添加一个“属性值非空”的查询条件
*
* @param propName 属性名,必须是字符串型属性
* @return 当前查询对象
*/
public CriteriaQuery notBlank(String propName) {
criterion = criterion.and(Criteria.notBlank(propName));
return this;
}
/**
* 添加一个“取反”的查询条件
*
* @param otherCriterion 原本的查询条件
* @return 当前查询对象
*/
public CriteriaQuery not(QueryCriterion otherCriterion) {
criterion = criterion.and(Criteria.not(otherCriterion));
return this;
}
/**
* 添加一个“与”的查询条件,即同时符合指定的几个查询条件
*
* @param aCriterion 另一个查询条件
* @return 当前查询对象
*/
public CriteriaQuery and(QueryCriterion aCriterion) {
if (aCriterion == null) {
return this;
}
criterion = criterion.and(aCriterion);
return this;
}
/**
* 添加一个“或”的查询条件,即符合指定的几个查询条件之一
*
* @param aCriterion 另一个查询条件
* @return 当前查询对象
*/
public CriteriaQuery or(QueryCriterion aCriterion) {
if (aCriterion == null) {
return this;
}
criterion = criterion.or(aCriterion);
return this;
}
/**
* 按指定的属性的升序对结果集排序
*
* @param propName 要排序的属性名
* @return 当前查询对象
*/
public CriteriaQuery asc(String propName) {
orderSettings.asc(propName);
return this;
}
/**
* 按指定的属性的降序对结果集排序
*
* @param propName 要排序的属性名
* @return 当前查询对象
*/
public CriteriaQuery desc(String propName) {
orderSettings.desc(propName);
return this;
}
/**
* 返回查询结果列表。
*
* @param <T> 查询结果的列表元素类型
* @return 查询结果。
*/
public <T> List<T> list() {
return repository.find(this);
}
/**
* 返回单条查询结果。
*
* @param <T> 查询结果的类型
* @return 查询结果。
*/
public <T> T singleResult() {
return repository.getSingleResult(this);
}
}