Spring Data JPA 动态拼接条件的通用设计模式
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.data.jpa.domain.Specification;
import com.xxx.controller.logManage.LogSearchParamDTO;
import com.xxx.controller.trade.TradeParams;
/**
* 改进方向 1:能不能 通过反射 ,只要---
* 相关知识请自行查阅JPA Criteria查询
// 过滤条件
// 1:过滤条件会被应用到SQL语句的FROM子句中。在criteria
// 查询中,查询条件通过Predicate或Expression实例应用到CriteriaQuery对象上。
// 2:这些条件使用 CriteriaQuery .where 方法应用到CriteriaQuery 对象上
// 3:CriteriaBuilder也作为Predicate实例的工厂,通过调用CriteriaBuilder 的条件方法(
// equal,notEqual, gt, ge,lt, le,between,like等)创建Predicate对象。
// 4:复合的Predicate 语句可以使用CriteriaBuilder的and, or andnot 方法构建。
* @author 小言
* @date 2017年11月27日
* @time 上午10:44:53
* @version ╮(╯▽╰)╭
*/
public class SpecificationBuilderForOperateLog {
public static <T> Specification buildSpecification(Class<T> clazz,
final LogSearchParamDTO logSearchParamDTO) {
return new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicate = new ArrayList<Predicate>();
Timestamp startTime = logSearchParamDTO.getStartTime();
Timestamp endTime = logSearchParamDTO.getEndTime();
// 时间段
if (startTime != null && endTime != null) {
predicate.add(cb.between(root.<Timestamp> get("logTime"), startTime, endTime));
}
// 操作日志查询栏
String searchCondition = logSearchParamDTO.getSearchCondition();
if (searchCondition != null && !searchCondition.equals("")) {
predicate.add(cb.or(cb.equal(root.<String> get("operatorName"), searchCondition),
cb.equal(root.<String> get("operatorId"), searchCondition)));
}
// 操作日志用户类型
String operatorType = logSearchParamDTO.getOperatorType();
System.out.println("operatorType=="+operatorType);
if (operatorType != null ){
predicate.add(cb.equal(root.<String> get("operatorType"), operatorType));
}
Predicate[] pre = new Predicate[predicate.size()];
// System.out.println("pre=="+predicate.toArray(pre));
query.where(predicate.toArray(pre));
return query.getRestriction();
}
};
}
}
下面是实际开发例子:
controller层
@Controller
@RequestMapping(value = "/operateLog")
public class BgOperateLogController { @Autowired
private BgOperateLogService bgOperateLogService; @ResponseBody
@PostMapping("/findOperateLogByCondition")
public Result findOperateLogByCondition(@RequestBody LogSearchParamDTO logSearchParamDTO) {
System.out.println("logSearchParamDTO="+logSearchParamDTO);
Map<String, Object> result = new HashMap<>();
String start = logSearchParamDTO.getStart();
String end = logSearchParamDTO.getEnd();
if (start != null && end == null) {
return new Result(1001, "操作日志查询错误,时间参数缺少结束时间", result);
}
if (end != null && start == null) {
return new Result(1001, "操作日志查询错误,时间参数缺少开始时间", result);
}
//时间
long startTimeTimestamp = 0L;
long endTimeTimestamp = System.currentTimeMillis();
if(start != null && end != null){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date startTime;
Date endTime;
try {
startTime = sdf.parse(start);
endTime = sdf.parse(end);
startTimeTimestamp = startTime.getTime();
endTimeTimestamp = endTime.getTime();
} catch (ParseException e) {
e.printStackTrace();
return new Result(1001, "操作日志查询错误,转换日期出错", result);
}
}
String condition = logSearchParamDTO.getSearchCondition();
Integer pageNumber = logSearchParamDTO.getPageNumber()-1;
Integer pageSize = logSearchParamDTO.getPageSize() ;
String operatorType =logSearchParamDTO.getOperatorType();
Page<BgOperateLog> findByCondition = bgOperateLogService.findByCondition(new Timestamp(startTimeTimestamp),
new Timestamp(endTimeTimestamp),
condition,operatorType, pageNumber, pageSize);
// 这些字段必须有,暂时没有做校验
List<BgOperateLog> list = findByCondition.getContent();
result.put("totalPages", findByCondition.getTotalPages());
result.put("pageNumber", pageNumber+1);
result.put("list", list);
return new Result(1002, "操作日志查询成功", result);
} }
BgOperateLogController
DTO
@Data
public class LogSearchParamDTO {
//前端传来的时间参数
private String start;
private String end;
private Timestamp startTime;
private Timestamp endTime;
private String searchCondition;
//操作日志查询参数
//操作用户类型(0,消费者,1商家,2后台人员)
private String operatorType;
private Integer pageNumber;
private Integer pageSize;
//登陆日志查询条件
public LogSearchParamDTO(Timestamp startTime, Timestamp endTime, String searchCondition) {
this.startTime = startTime;
this.endTime = endTime;
this.searchCondition = searchCondition;
}
public LogSearchParamDTO() {}
//操作日志查询条件
public LogSearchParamDTO(Timestamp startTime, Timestamp endTime, String searchCondition, String operatorType) {
this.startTime = startTime;
this.endTime = endTime;
this.searchCondition = searchCondition;
this.operatorType = operatorType;
}
}
LogSearchParamDTO
service 层
@Override
public Page<BgOperateLog> findByCondition(Timestamp start,
Timestamp end, String condition ,String operatorType,
int pageNumber, int pageSize) {
Sort sort = new Sort(Sort.Direction.DESC, "logTime");
Pageable pageable = new PageRequest(pageNumber, pageSize, sort);
LogSearchParamDTO operateLog = new LogSearchParamDTO(start, end, condition,operatorType);
Page<BgOperateLog> page = bgOperateLogDao
.findAll(SpecificationBuilderForOperateLog.buildSpecification(BgOperateLog.class,operateLog), pageable);
return page;
}
dao层
import java.io.Serializable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
import com.xxx.entity.BgOperateLog;
@Repository
public interface BgOperateLogDao extends JpaRepository<BgOperateLog, Serializable>,JpaSpecificationExecutor<BgOperateLog>{}
entity层
@Data
@Entity
public class BgOperateLog implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String logText;
private String operatorId;
private String operatorName;
private String operatorType;
private String ip;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Timestamp logTime;
}
转自:
https://blog.csdn.net/dgutliangxuan/article/details/78644464
https://blog.csdn.net/u011726984/article/details/72627706
参考:
https://www.cnblogs.com/vcmq/p/9484398.html
https://www.cnblogs.com/g-smile/p/9177841.html
Spring Data JPA 动态拼接条件的通用设计模式的更多相关文章
- springboot整合spring data jpa 动态查询
Spring Data JPA虽然大大的简化了持久层的开发,但是在实际开发中,很多地方都需要高级动态查询,在实现动态查询时我们需要用到Criteria API,主要是以下三个: 1.Criteria ...
- Spring Data JPA 复杂/多条件组合查询
1: 编写DAO类或接口 dao类/接口 需继承 public interface JpaSpecificationExecutor<T> 接口: 如果需要分页,还可继承 public ...
- Spring MVC和Spring Data JPA之按条件查询和分页(kkpaper分页组件)
推荐视频:尚硅谷Spring Data JPA视频教程,一学就会,百度一下就有, 后台代码:在DAO层继承Spring Data JPA的PagingAndSortingRepository接口实现的 ...
- spring data jpa实现多条件查询(分页和不分页)
目前的spring data jpa已经帮我们干了CRUD的大部分活了,但如果有些活它干不了(CrudRepository接口中没定义),那么只能由我们自己干了.这里要说的就是在它的框架里,如何实现自 ...
- spring data jpa 动态查询(工具类封装)
利用JPA的Specification<T>接口和元模型就实现动态查询了.但是这样每一个需要动态查询的地方都需要写一个这样类似的findByConditions方法,小型项目还好,大型项目 ...
- 序列化表单为json对象,datagrid带额外参提交一次查询 后台用Spring data JPA 实现带条件的分页查询 多表关联查询
查询窗口中可以设置很多查询条件 表单中输入的内容转为datagrid的load方法所需的查询条件向原请求地址再次提出新的查询,将结果显示在datagrid中 转换方法看代码注释 <td cols ...
- Spring Data JPA动态查询(多条件and)
entity: @Entity @Table(name = "data_illustration") public class Test { @Id @GenericGenerat ...
- Spring Data JPA 复杂/多条件组合分页查询
推荐视频: http://www.icoolxue.com/album/show/358 public Map<String, Object> getWeeklyBySearch(fina ...
- 【spring data jpa】带有条件的查询后分页和不带条件查询后分页实现
一.不带有动态条件的查询 分页的实现 实例代码: controller:返回的是Page<>对象 @Controller @RequestMapping(value = "/eg ...
随机推荐
- java多线程ExecutorService
1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...
- verilog 实用的小技巧
(之后还会持续的更新) 移位操作的实现: verilog有一种非常简单的移位操作实例如下: reg [3:0] source; reg out; {out,source[3:0]}={source[3 ...
- Vue自行封装常用组件-文本提示
使用方法:1.在父组件中引入"toast.vue" //import toast from "./toast"; 2.在父组件中注册 toast //compo ...
- 【spoj 5971】lcmsum
全场都 AK 了就我爆 0 了 题意 \(t\) 组询问,每组询问给定 \(n\),求 \(\sum\limits_{k=1}^n [n,k]\).其中 \([a,b]\) 表示 \(a\) 和 \( ...
- CodeForces - 1209F Koala and Notebook(拆边+BFS)
题意:给定一个n个点m条边的无向图,边权分别为1-m,从起点1出发,每经过一条边就把边权以字符串的形式加入末尾,求到达其他每个点的最小字符串(长度不同的短的更小,否则字典序小的更小). 思路很巧妙,将 ...
- Acwing-284-金字塔(区间DP)
链接: https://www.acwing.com/problem/content/description/286/ 题意: 虽然探索金字塔是极其老套的剧情,但是有一队探险家还是到了某金字塔脚下. ...
- yaml格式介绍
一.简介 YAML 语言(发音 /ˈjæməl/ )的设计目标,就是方便人类读写.它实质上是一种通用的数据串行化格式. 它的基本语法规则如下. 大小写敏感 使用缩进表示层级关系 缩进时不允许使用Tab ...
- MaxCompute - ODPS重装上阵 第六弹 - User Defined Type
MaxCompute(原ODPS)是阿里云自主研发的具有业界领先水平的分布式大数据处理平台, 尤其在集团内部得到广泛应用,支撑了多个BU的核心业务. MaxCompute除了持续优化性能外,也致力于提 ...
- OpenCV笔记(4)(直方图、傅里叶变换、高低通滤波)
一.直方图 用于统计图片中各像素值: # 画一个图像各通道的直方图 def draw_hist(img): color = ('b', 'g', 'r') for i, col in enumerat ...
- head first 设计模式笔记3-装饰者模式:星巴兹饮料
开放原则:类应该对扩展开放,对修改关闭. - 上篇博客中的观察者模式中,通过加入新的观察者,我们可以在任何时候扩展主题(Subject),而且不需向主题中添加代码. - 装饰者模式也完全遵循开放原则. ...