JPA的官方文档对于复杂查询和一些函数使用上并不友好,这里示范一些使用方法。
这里通过结合Specification接口和封装一个工具类来实现相应功能,直接上代码供大家参考。
JpaUtil工具类,这里只展示单行查询,如果需要查询类似groupby的多行结果,可以通过Tuple数组整个返回出来得到结果。
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.Tuple;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.List;
@Component
public class JpaUtil {
@Resource
private EntityManager entityManager;
public <T> Tuple findOne(Specification<T> specification, Class<T> modelClass) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> query = criteriaBuilder.createTupleQuery();
Root<T> root = query.from(modelClass);
Predicate predicate = specification.toPredicate(root, query, criteriaBuilder);
if (predicate != null) {
query.where(predicate);
}
List<Tuple> result = entityManager.createQuery(query).getResultList();
return result.size() > 0 ? result.get(0) : null;
}
}
Specification示例
import org.springframework.data.jpa.domain.Specification;
public class DataSpecification {
public static Specification<DataModel> sumByNo(String no) {
return ((root, query, criteriaBuilder) -> {
query.multiselect(
root.get("name").alias("name")
, criteriaBuilder.sum(root.get("mileage")).alias("mileage")
, criteriaBuilder.sum(root.get("seconds")).alias("seconds"));
return criteriaBuilder.equal(root.get("no"), no);
});
}
}
DataModel可以自行定义,有对应字段即可。