JPA复杂查询时间查询分页排序
JPA复杂查询时间查询分页排序
JPA复杂查询时间查询分页排序,工作上用到,因为项目是jpa,记录。代码囊括了:查询条件+时间范围+分页+排序
其实我也不太想用jpa,但是他也有优点,操作可以兼容多种数据库,mybatis也能,需要额外写代码。但我还是喜欢mybatis
public ResponseResultPage<AlarmEventHistoryPo> getHistory(String eventId, Integer page, Integer size, String startTime, String endTime, Boolean onlyHealthy) {
//直接使用匿名内部类实现接口
Specification<AlarmEventHistoryPo> specification = new Specification<AlarmEventHistoryPo>() {
@Override
public Predicate toPredicate(Root<AlarmEventHistoryPo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicateList = new ArrayList<>();
// 根据字段
predicateList.add(cb.equal(root.get("eventId").as(String.class), eventId));
// 开始时间
if (StringUtils.isNotEmpty(startTime)) {
predicateList.add(cb.greaterThanOrEqualTo(root.get("createDate").as(String.class), startTime));
}
// 结束时间
if (StringUtils.isNotEmpty(endTime)) {
predicateList.add(cb.lessThanOrEqualTo(root.get("createDate").as(String.class), endTime));
}
if (onlyHealthy != null && onlyHealthy) {// and ( pre or pre )
Predicate pred1 = cb.equal(root.get("type").as(String.class), "auto_healthy");
Predicate pred2 = cb.equal(root.get("type").as(String.class), "user_healthy");
predicateList.add(cb.or(pred1, pred2));
}
Predicate[] pre = new Predicate[predicateList.size()];
pre = predicateList.toArray(pre);
return query.where(pre).getRestriction();
}
};
// 分页 + 排序
Pageable pageable = PageRequest.of(page - 1, size, new Sort(Sort.Direction.DESC, "createDate"));
Page<AlarmEventHistoryPo> alarmEventHistoryPos = alarmEventHistoryPoDao.findAll(specification, pageable);
if (alarmEventHistoryPos == null) {
return new ResponseResultPage<>(null);
}
}
@Repository
public interface AlarmEventHistoryPoDao extends JpaRepository<AlarmEventHistoryPo, String> {
Page<AlarmEventHistoryPo> findAll(Specification specification, Pageable pageable);
}
2022年7月18日 追加修改----------------------↓↓↓↓↓↓↓↓↓↓
我发现有同学收藏点赞,在高版本hibernate已经注解弃用,不建议使用以上的方式,jpa没有模板引擎,整合其他模板引擎就太复杂。个人建议简单封装Query
查询即可,例如下面这样:
import cn.hutool.core.collection.CollUtil;
import org.hibernate.Session;
import org.hibernate.query.Query;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author lingkang
* Created by 2022/7/18
* 封装原因:jpa整合模板引擎太复杂
*/
public class ComplexQueryUtils {
/**
* 对复杂查询的简单封装,有SQL注入处理
* 若有入参,应该从 ?, ?, ? ... 算起, 例如 condition.put(" and vo.id = ?","svcrvtf-0qdYxo4q");
*
* @param session
* @param sql
* @param condition
* @return
*/
public static Query query(Session session, String sql, LinkedHashMap<String, Object> condition) {
if (CollUtil.isEmpty(condition)) {
return session.createQuery(sql);
}
StringBuilder sqlBuilder = new StringBuilder(sql);
for (Map.Entry<String, Object> entry : condition.entrySet())
sqlBuilder.append(entry.getKey());
// 将 ? ? ? 替换成 ?1 ?2 ?3
int i = 1;
int index = sqlBuilder.indexOf("?");
if (index != -1)
for (; ; ) {
sqlBuilder.replace(index, ++index, "?" + i++);
index = sqlBuilder.indexOf("?", index);
if (index == -1)
break;
}
Query query = session.createQuery(sqlBuilder.toString());
i = 1;
for (Map.Entry<String, Object> entry : condition.entrySet())
if (entry.getValue() != null) {
query.setParameter(i++, entry.getValue());
}
return query;
}
}
使用方法:
TenantVo tenant = UserUtils.getCurrentTenant();
LinkedHashMap<String, Object> condition = new LinkedHashMap<>();
if (tenant != null) {
condition.put(" and fv.tenantId='" + tenant.getId() + "'", null);// 存在SQL注入
}
condition.put(" and vo.id = ?1","svcrvtf-0qdYxo4q");// SQL注入过滤
// AFA
List<ServiceVersionResourceVersionToFileVO> afa = ComplexQueryUtils.query(
serviceDao.getSession(),
"select vo from service vo left join File fv on vo.file.id=fv.id" +
" where vo.serviceVersion.service.id is not null" +
" and fv.id is not null ",
condition
)
// .setFirstResult(9).setMaxResults(10)// 分页,第 10到20条数据
.list();