Spring Data JPA的Specifications和Querydsl
来源:互联网 发布:淘宝中国造 编辑:程序博客网 时间:2024/05/19 16:27
Specifications
要想使用Specifications,必须继承JpaSpecificationExecutor接口。该接口扩展了查询方法findAll:
条件不分页:List findAll(Specification spec);
条件+分页:Page findAll(Specification spec, Pageable pageable);
Specification接口:
public interface Specification<T> { Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb); }
Demo1代码:
@Action("subarea_listPage") public String listPage() throws Exception{ //Spring Data实现QBC方式查询 //需要两个参数对象:Specification(条件规范)和Pageable(分页规范) //1.------分页对象 Pageable pageable = new PageRequest(page-1, rows); //2.-------条件对象 Specification<Subarea> specification = new Specification<Subarea>() { //参数1:Root:根对象(要查询的主实体对象) //参数2:CriteriaQuery:条件查询对象 //参数3:CriteriaBuilder:条件查询的构建对象,类似于criteria编程方式 //返回:Predicate:where后面的条件包装对象 @Override public Predicate toPredicate(Root<Subarea> root, CriteriaQuery<?> query, CriteriaBuilder cb) { //定义条件对象列表 List<Predicate> pList = new ArrayList<>(); //单表条件对象构建(定区编码和地区关键字在分区表中) //地区关键字条件 if (StringUtils.isNotBlank(model.getAddresskey())) { //参数1:条件表达式 //参数2:值 Predicate p1 = cb.equal(root.get("addresskey"), model.getAddresskey()); pList.add(p1); } //定区关键字条件 if (model.getDecidedZone() != null && StringUtils.isNotBlank(model.getDecidedZone().getId())) { //参数1:条件表达式 //参数2:值 Predicate p2 = cb.equal(root.get("decidedZone").as(DecidedZone.class), model.getDecidedZone()); pList.add(p2); } //-----多表关联条件对象 if (model.getRegion() != null) { //获取连接实体对象 //参数1:连接的目标对象;参数2:多表连接的类型 Join<Subarea, Region> regionJoin = root.join(root.getModel().getSingularAttribute("region",Region.class),JoinType.INNER); //要连接的实体条件构建 //省份条件 if (model.getRegion() != null && StringUtils.isNotBlank(model.getRegion().getProvince())) { Predicate p3 = cb.like(regionJoin.get("province").as(String.class), "%"+model.getRegion().getProvince()+"%"); pList.add(p3); } //城市条件 if (model.getRegion() != null && StringUtils.isNotBlank(model.getRegion().getCity())) { Predicate p4 = cb.like(regionJoin.get("city").as(String.class), "%"+model.getRegion().getCity()+"%"); pList.add(p4); } //区域条件 if (model.getRegion() != null && StringUtils.isNotBlank(model.getRegion().getDistrict())) { Predicate p5 = cb.like(regionJoin.get("district").as(String.class), "%"+model.getRegion().getDistrict()+"%"); pList.add(p5); } } //pList转换为具体类型的数组 Predicate[] predicate = pList.toArray(new Predicate[0]); //将条件进行汇总并返回 return cb.and(predicate); } }; //调用servic进行查询 Page<Subarea> pageResponse = subareaService.findSubareaListPage(specification,pageable); //将结果转换为map格式 Map<String,Object> resultMap = new HashMap<String,Object>(); resultMap.put("total", pageResponse.getTotalElements()); resultMap.put("rows", pageResponse.getContent()); //将结果压入栈顶 pushToValueStack(resultMap); //返回json类型 return JSON; }
Demo2代码:
@Action("decidedzone_listPage") public String decidedzone_listPage() throws Exception{ //分页数据 Pageable pageable = new PageRequest(page-1, rows); //业务条件 Specification<DecidedZone> specification =new Specification<DecidedZone>(){ @Override public Predicate toPredicate(Root<DecidedZone> root, CriteriaQuery<?> query, CriteriaBuilder cb) { //条件表达式集合 Predicate predicateAnd = cb.conjunction();//交集 Predicate predicateOr = cb.disjunction();//并集 //定区编码条件 if (StringUtils.isNotBlank(model.getId())) { predicateAnd.getExpressions().add(cb.equal(root.get("id").as(String.class), model.getId())); } //所属单位 if (model.getStaff() != null) { //多表关联 root.join(root.getModel().getSingularAttribute("staff",Staff.class),JoinType.LEFT); //根据取派员的单位作为条件 if (StringUtils.isNotBlank(model.getStaff().getStation())) { predicateAnd.getExpressions().add(cb.like(root.get("station").as(String.class), "%"+model.getStaff().getStation()+"%")); } } //是否关联分区 if (StringUtils.isNotBlank(hasSubarea)) { if (hasSubarea.equals("1")) { predicateAnd.getExpressions().add(cb.isNotEmpty(root.get("subareas").as(Set.class))); } else { predicateAnd.getExpressions().add(cb.isEmpty(root.get("subareas").as(Set.class))); } } return predicateAnd; } }; //调用service进行查询 Page<DecidedZone> pageResponse = decidedZoneService.findDecidedZoneListPage(pageable,specification); //结果map Map<String,Object> resultMap = new HashMap<String,Object>(); resultMap.put("total", pageResponse.getTotalElements()); resultMap.put("rows", pageResponse.getContent()); //把结果压入栈顶 pushToValueStack(resultMap); //返回json类型 return JSON; }
Querydsl
Querydsl的开源项目也提供了类似的解决方案,但是实现有所不同,提供了更有好的API,而且不仅支持JPA,还支持hibernate,JDO,Lucene,JDBC甚至是原始集合的查询。
为了使用Querydsl,需要在pom.xml中引入依赖并且配置一个额外的APT插件。
<plugin> <groupId>com.mysema.maven</groupId> <artifactId>maven-apt-plugin</artifactId> <version>1.0</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>process</goal> </goals> <configuration> <outputDirectory>target/generated-sources</outputDirectory> <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor> </configuration> </execution> </executions> </plugin>
BooleanExpressions还可以直接重用,免去使用更多包装方法的写法,要执行查询,跟Specification类似,让repository继承QueryDslPredicateExecutor接口即可。
public interface CustomerRepository extends JpaRepository<Customer>, QueryDslPredicateExecutor { // Your query methods here } QCustomer customer = QCustomer.customer; LocalDate today = new LocalDate(); BooleanExpression customerHasBirthday = customer.birthday.eq(today); BooleanExpression isLongTermCustomer = customer.createdAt.lt(today.minusYears(2)); customerRepository.findAll(customerHasBirthday.and(isLongTermCustomer));
0 0
- Spring Data JPA的Specifications和Querydsl
- Spring Data JPA进阶-Specifications和Querydsl
- Spring Data JPA进阶——Specifications和Querydsl
- Spring Data JPA进阶——Specifications和Querydsl
- Spring Data JPA进阶——Specifications和Querydsl
- Spring Data JPA教程, 第五部分: Querydsl(未翻译)
- Spring data JPA中使用Specifications动态构建查询
- Spring data JPA中使用Specifications动态构建查询
- jpa和spring data jpa的理解
- JPA,spring data jpa和其他jpa框架的关系
- JPA与QueryDsl的学习
- JPA和spring data
- Hibernate和Spring data jpa的区别?
- Spring-data-rest 和Spring-data-jpa
- JPA和Spring-Data-JPA简介
- spring data jpa和hibernate jpa
- JPA和Spring-Data-JPA简介
- JPA和Spring-Data-JPA简介
- 图解项目管理【基础】
- 数据结构实验:连通分量个数
- Netty源码解读(一)概述
- POJ3109-Inner Vertices-离散化+扫描线
- ionic的切换效果实现——以登录页密码显示隐藏切换为例
- Spring Data JPA的Specifications和Querydsl
- Java 字节码操控框架ASM(三):修改 classes
- node-webkit项目最小化到托盘(右下角)
- 情感分析负面词汇收集
- Activity 设置style 改变为dialog后设置不显示title
- 图结构练习——最小生成树
- 从C到C++的升级之命名空间和数据类型
- Android NDK: From Elementary to Expert Episode 2
- 解决"Error detected while processing /root/.vimrc:"