class Specification {
public static void main(String[] args) {
// 底层实现原理,Specification接口底层就是利用EntityManager实现
EntityManager entityManager = SpringUtil.getBean(EntityManager.class);
// 固定套路,总共十一步
// 第一步: 获取条件构造器
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// 第二步: 构造标准查询API,这里使用Object[]而不是使用User是因为下面有别名,函数的情况,所以用实体无法接收,还有很多的方式
CriteriaQuery<Object[]> criteriaQuery = criteriaBuilder.createQuery(Object[].class);
// 第三步: 指定查询的根实体,说白了就是主表内容,Root就表示主表的字段信息
Root<User> root = criteriaQuery.from(User.class);
// 第四步(可选): 多表关联,User表与IdCard表关联,使用的都是属性名,自动设置连接条件
Join<User, IdCard> join = root.join("idCard", JoinType.LEFT);
// 如果设置一对多,或者多对多,使用joinCollection
// Join<User, Address> join = root.joinCollection("idCard", JoinType.LEFT);
// 第四-五步: 要查询的字段汇总
// 查询所有
// criteriaQuery.select(root);
// 查询指定字段和使用聚合函数并且取别名
// 给字段取别名,记得接受结果的返回值的属性需要对应上
// 注意: 控制台打印的SQL没有取别名,Hibernate生成的SQL语句不会包含Criteria API中设置的别名
Selection<String> name = root.get("name").as(String.class).alias("name");
Selection<Integer> age = root.get("age").as(Integer.class).alias("age");
// 给聚合函数取别名
Expression<Long> count = criteriaBuilder.count(root.get("age"));
criteriaBuilder.construct(Long.class, count.alias("count"));
// 查询字段,其中,root表示主表select root.*,join表示关联表select join.*
criteriaQuery.multiselect(root, join, name, age, count);
// 第五步: 构建条件并设置条件,tip: 下面criteriaQuery操作实际上不区分先后顺序
// 如果要设置主表的字段条件,使用root.get("字段名")
// 如果要设置关联表的字段条件,join.get("字段名")
Predicate rootIsDelete = criteriaBuilder.isFalse(join.get("deleted"));
Predicate idCardDelete = criteriaBuilder.isFalse(root.get("deleted"));
// 如果要使用and,或or,直接使用conjunction,disjunction,构建一个空条件Predicate,然后在进行拼接和and,or方法是一样的
Predicate andEmptyPredicate = criteriaBuilder.conjunction();
// 构造条件
Predicate nameEqualPredicate = criteriaBuilder.equal(root.get("name"), "luck");
Predicate ageGePredicate = criteriaBuilder.ge(root.get("age"), 10);
// 将构造条件统一存入到空的Predicate,并且他们使用and连接
// user.name = 'luck' and user.age >= 10
andEmptyPredicate.getExpressions().add(nameEqualPredicate);
andEmptyPredicate.getExpressions().add(ageGePredicate);
// 上面两行代码等于下面一行代码
// user.name = 'luck' and user.age >= 10
Predicate andPredicate = criteriaBuilder.and(nameEqualPredicate, ageGePredicate);
// 将构造条件统一存入到空的Predicate,并且他们使用or连接
// user.name = 'luck' or user.age >= 10
Predicate orEmptyPredicate = criteriaBuilder.disjunction();
orEmptyPredicate.getExpressions().add(nameEqualPredicate);
orEmptyPredicate.getExpressions().add(ageGePredicate);
// 上面两行代码等于下面一行代码
// user.name = 'luck' or user.age >= 10
Predicate orPredicate = criteriaBuilder.or(nameEqualPredicate, ageGePredicate);
// 如果要实现 (x1) or (x2)这种情况,那么x1和x2都是一个使用and连接的Predicate,然后x1和x2使用or连接
Predicate twoAndOrPredicate = criteriaBuilder.or(andPredicate, andEmptyPredicate);
// 嵌套也是一样的(x1 or x2) and (x3 or x4)
// 步骤1: x1和x2对应Predicate使用or进行连接,结果为x1x2
// 步骤2: x3和x4对应Predicate使用or进行连接,结果为x3x4
// 步骤3: 再将步骤一结果和步骤二结果x1x2与x3x4使用and进行连接得到x1x2Andx3x4,最终作为结果
// (user.name = ? or username = ?) and (user.age >= 100 or user.age < 10)
Predicate x1 = criteriaBuilder.equal(root.get("name"), "luck");
Predicate x2 = criteriaBuilder.equal(root.get("name"), "java");
Predicate x1x2 = criteriaBuilder.or(x1, x2);
Predicate x3 = criteriaBuilder.ge(root.get("age"), 100);
Predicate x4 = criteriaBuilder.lt(root.get("age"), 10);
Predicate x3x4 = criteriaBuilder.or(x3, x4);
Predicate x1x2Andx3x4 = criteriaBuilder.and(x1x2, x3x4);
// 以上所有构建的条件都可以使用上,这个就是为了说明sql,上面构造的条件意义不大
criteriaQuery.where(rootIsDelete, idCardDelete, orPredicate, twoAndOrPredicate, x1x2Andx3x4);
// 第六步(可选): 构造分组条件并设置
// 指定字段分组,可以有多个
criteriaQuery.groupBy(root.get("age"));
// 第七步(可选): 构造分组后条件并设置
// 这个和上面讲的where一样
criteriaQuery.having();
// 第八步(可选): 构造排序条件并设置
// 指定排序字段,并且设置排序方式
criteriaQuery.orderBy(criteriaBuilder.asc(root.get("age")));
// 第九步: 使用标准查询API(CriteriaQuery)构建一个可执行标准查询的Query对象
TypedQuery<Object[]> query = entityManager.createQuery(criteriaQuery);
// 第十步(可选): 设置分页参数,limit 1,10
query.setFirstResult(1).setMaxResults(10);
// 第十一步: 执行查询,获取结果
List<Object[]> users = query.getResultList();
for (Object[] user : users) {
for (Object u : user) {
System.out.print(u + ",");
}
System.out.println();
}
System.out.println(users);
}
}
JPA中,QBC查询,JpaSpecificationExecutor,Specification总结
最新推荐文章于 2024-04-10 02:25:23 发布
本文详细介绍了如何在Java中使用JPA的CriteriaBuilder和CriteriaQuery进行数据库查询,包括条件构造、多表关联、字段选择、分组、排序以及分页等操作。
摘要由CSDN通过智能技术生成