最近有一个需求:
有三个查询条件,如果适用 JPA 最常见的形式
则需要加很多判断条件
如果采用最原生的 sql 哪一个筛选条件传值了
那么就拼接一下 sql 会方便很多
例如:
if(type!=null){
拼接 where type = xxx
}
if(mobile!=“”){
拼接 where mobile=“xxxxxx”
}
if(startTime!=null){
拼接 where endTime xxxxxx
}
三个判断条件写出来就解决了,所以这里记录一下如何适用 JPA 的原生 SQL
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class StaffGetNewCouponListV2ApiProcesser extends BaseApiProcesser {
@Autowired
private EntityManager entityManager;
private final static String WHERE = " where ";
private final static String AND = " and ";
@Override
public Map<String, Object> processRequest() throws InvalidParameterException, FailException {
Integer type = checkIntegerParameter("type", null);
Date startTime = checkDateParameter("startTime", null);
Date endTime = checkDateParameter("endTime", null);
String endTimeString = "";
String startTimeString = "";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if (endTime != null) {
endTimeString = simpleDateFormat.format(endTime);
}
if (startTime != null) {
startTimeString = simpleDateFormat.format(startTime);
}
boolean whereFlag = false;
String sql = "select * from new_coupon_detail";
if (type != null) {
if (whereFlag == false) {
whereFlag = true;
sql += WHERE;
} else {
sql += AND;
}
sql += "range_of_application= " + type;
}
if (startTime != null) {
if (whereFlag == false) {
whereFlag = true;
sql += WHERE;
} else {
sql += AND;
}
sql += "start_time <=" + "'" + startTimeString + "'";
}
if (endTime != null) {
if (whereFlag == false) {
whereFlag = true;
sql += WHERE;
} else {
sql += AND;
}
sql += "end_time>=" + "'" + endTimeString + "'";
}
Query nativeQuery = entityManager.createNativeQuery(sql,NewCouponDetail.class);
List<NewCouponDetail> resultList = nativeQuery.getResultList();
for (NewCouponDetail newCouponDetail : resultList) {
System.out.println(newCouponDetail);
}
return null;
}
}
这样写出来的 原生SQL 是可以的
但是在 JPA 中,还提供了一种方法 那就是 Specification
使用这个的前提是: repository 继承 JpaSpecificationExecutor
@Repository
public interface XXXXXRepository extends JpaRepository<XXXXXX, Integer>, JpaSpecificationExecutor<XXXXX> {
}
public void findBySpection(Integer type, Date startTime, Date endTime) {
/*分页参数*/
Pageable pageable = PageRequest.of(0, 20, Sort.Direction.ASC, "startTime");
newCouponDetailRepository.findAll(new Specification<NewCouponDetail>() {
@Override
public Predicate toPredicate(Root<NewCouponDetail> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
/*条件的集合*/
ArrayList<Predicate> predicateList = new ArrayList<>();
if (type != null) {
/*实体类的某个字段并将其指定为Integer类型 equal 传入的参数*/
Predicate rangeOfApplication = criteriaBuilder.equal(root.get("rangeOfApplication").as(Integer.class), type);
predicateList.add(rangeOfApplication);
}
if (startTime != null) {
/*实体类的 startTime <= 传入的参数*/
Predicate startTime1 = criteriaBuilder.lessThanOrEqualTo(root.get("startTime").as(Date.class), startTime);
predicateList.add(startTime1);
}
if (endTime != null) {
/*实体类的 endTime >= 传入的参数*/
Predicate endTime1 = criteriaBuilder.greaterThanOrEqualTo(root.get("endTime").as(Date.class), endTime);
predicateList.add(endTime1);
}
//使用数组作为最终返回值的条件
Predicate[] predicates = new Predicate[predicateList.size()];
//将集合转换成数组
predicates = predicateList.toArray(predicates);
//合并条件
return criteriaBuilder.and(predicates);
}
}, pageable);
}