共计 3205 个字符,预计需要花费 9 分钟才能阅读完成。
引言
之前在项目中经常使用单表查询,在涉及到多个实体间查询时,往往直接用云智的综合查询库,怎么查的,一概不知;
在写 Alice 的补考管理时,需求:总成绩小于(成绩设置)及格成绩的显示出来,综合查询库不能使用,因此对多实体之间的查询有了一个初步的了解。
概述
- 多表查询需要 SpringData 提供的
JpaSpecificationExecutor
接口 -
实体仓库需要继承
JpaSpecificationExecutor
public interface ScoreRepository extends CrudRepository<Score, Long>, JpaSpecificationExecutor<Score> {}
-
实现
JpaSpecificationExecutor
接口中toPredicate
方法public static Specification<Score> base(final Map<String, Object> map) {return new Specification<Score>() { @Override public Predicate toPredicate(Root<Score> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {}}
构建查询条件
logger.info("构建查询条件,总成绩低于及格成绩");
Predicate makeupScorePredicate = criteriaBuilder
.lessThan(root.get("totalScore").as(Float.class),
root.join("courseArrangement")
.join("course")
.join("scoreSet")
.get("passScore").as(Float.class));
and
、or
连接查询条件
在此以 and
举例说明:
private Predicate predicate = null;
private CriteriaBuilder criteriaBuilder;
private void andPredicate(Predicate predicate) {
// 如果传入查询条件不为空
if (null != predicate) {if (null == this.predicate) {
// 如果该方法之前没有查询条件,则直接赋值
this.predicate = predicate;
} else {
// 否则,使用 criteriaBuilder 的与将已有查询条件和新查询条件用 and 连接
this.predicate = this.criteriaBuilder.and(this.predicate, predicate);
}
}
}
改进
张喜硕组长说:之前那样写不太好,不容易理解。
在构建查询条件是我们还可以这样写:
logger.info("构建查询条件,总成绩低于及格成绩");
Predicate makeupScorePredicate = root.get("totalScore").as(Float.class)
.lessThan(root.join("courseArrangement")
.join("course")
.join("scoreSet")
.get("passScore").as(Float.class))
这样写是不是就简单明了了呢!很容易看出查询的条件是:总成绩低于及格成绩
总结
平时都是使用云智仓库进行综合查询,没有什么感觉,就是会用,原理也不清楚,总是很模糊;直到有一天迫不得已自己去写了,才会对它了解更深一层。
在此,感谢张喜硕组长
参考代码
/**
* 根据查询条件返回查询成绩
*
* @param map 查询条件
*/
public static Specification<Score> base(final Map<String, Object> map) {return new Specification<Score>() {
private Predicate predicate = null;
private CriteriaBuilder criteriaBuilder;
// 设置 and 谓语. 注意,这里只能设置 and 关系的谓语,如果谓语为 OR,则需要手动设置
private void andPredicate(Predicate predicate) {if (null != predicate) {if (null == this.predicate) {this.predicate = predicate;} else {this.predicate = this.criteriaBuilder.and(this.predicate, predicate);
}
}
}
@Override
public Predicate toPredicate(Root<Score> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {logger.info("设置私有变量");
this.criteriaBuilder = criteriaBuilder;
logger.info("总评低于及格成绩");
Predicate makeupScorePredicate = criteriaBuilder.lessThan(root.get("totalScore").as(Float.class), root.join("courseArrangement").join("course").join("scoreSet").get("passScore").as(Float.class));
this.andPredicate(makeupScorePredicate);
if (null != map.get("semesterId")) {logger.info("传入了学期信息");
Predicate semesterIdPredicate = criteriaBuilder.equal(root.join("courseArrangement").join("semester").get("id").as(Long.class), map.get("semesterId"));
this.andPredicate(semesterIdPredicate);
}
if (null != map.get("gradeId")) {logger.info("传入了年级信息");
Predicate gradeIdPredicate = criteriaBuilder.equal(root.join("student").join("klass").join("grade").get("id").as(Long.class), map.get("gradeId"));
this.andPredicate(gradeIdPredicate);
}
if (null != map.get("majorId")) {logger.info("传入了专业信息");
Predicate majorIdPredicate = criteriaBuilder.equal(root.join("courseArrangement").join("course").join("major").get("id").as(Long.class), map.get("majorId"));
this.andPredicate(majorIdPredicate);
}
if (null != this.predicate) {criteriaQuery.where(criteriaBuilder.and(this.predicate));
}
return criteriaQuery.getRestriction();}
};
}
正文完
发表至: java
2019-05-24