SpringData利用Specification多条件查询

wx60c1a9177952c 2021-07-20 04:21:02
spring Spring教程


SpringData JPA遵循Eric Evans在Domain Driver Design一书中的规范,让你可以使用编程方式来构建多条件查询。

快速开始

关于SpringBoot与JPA的快速整合,已经在这篇文章中写的非常详细:SpringBoot整合Spring Data JPA,一些配置部分就不再赘述了,我们直接创建一个条件丰富一些的实体类做测试。

创建实体类
@Entity(name = "t_blog")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 文章名称
*/
private String name;
/**
* 作者
*/
private String author;
/**
* 状态, 0代表未发布, 1代表已发布
*/
private Integer status;
/**
* 发布时间
*/
@Column(name = "publish_time")
private Date publishTime;
/**
* 更新时间
*/
@Column(name = "update_time")
private Date updateTime;
}
继承JpaSpecificationExecutor接口
public interface BlogDao extends JpaRepository<Blog, Long>, JpaSpecificationExecutor<Blog> {
}

继承JpaSpecificationExecutor之后,便能够使用其中提供Specification相关的方法:

public interface JpaSpecificationExecutor<T> {
Optional<T> findOne(@Nullable Specification<T> spec);
List<T> findAll(@Nullable Specification<T> spec);
Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable);
List<T> findAll(@Nullable Specification<T> spec, Sort sort);
long count(@Nullable Specification<T> spec);
}

SpringData利用Specification多条件查询

 

Specification接口

可以看到,他们都需要一个Specification接口对象,而且可以注意到这个接口中有Java8新增的接口规范,如static方法、default方法,以及仅有一个抽象方法,可以作为函数式接口,传入Lambda表达式简化书写。

这些方法的用法其实见名知义对吧。

public interface Specification<T> extends Serializable {
long serialVersionUID = 1L;
static <T> Specification<T> not(@Nullable Specification<T> spec) {
return spec == null //
? (root, query, builder) -> null //
: (root, query, builder) -> builder.not(spec.toPredicate(root, query, builder));
}
static <T> Specification<T> where(@Nullable Specification<T> spec) {
return spec == null ? (root, query, builder) -> null : spec;
}
default Specification<T> and(@Nullable Specification<T> other) {
return SpecificationComposition.composed(this, other, CriteriaBuilder::and);
}
default Specification<T> or(@Nullable Specification<T> other) {
return SpecificationComposition.composed(this, other, CriteriaBuilder::or);
}
@Nullable
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder);
}
复杂查询
@Test
public void findByExample() {
Specification<Blog> specification = new Specification<Blog>() {
@Override
public Predicate toPredicate(Root<Blog> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicates = new LinkedList<>();
predicates.add(cb.equal(root.get("status"), 1)); // 查询status状态为1
predicates.add(cb.like(root.get("author"), "%summer%")); // author名称中存在summer
predicates.add(cb.between(root.get("publishTime"), // 发布时间7天前至今
Date.from(Instant.now().minus(Duration.ofDays(7))), new Date()));
return query.where(predicates.toArray(new Predicate[0])).getRestriction();
}
};
// 按照条件查询,并按照publish_time升序
List<Blog> blogs
= blogDao.findAll(specification, Sort.by(Sort.Direction.ASC, "publishTime"));
blogs.forEach(System.out::println);
}

最后的查询语句如下:

select id, author, name,publish_time,status,update_time from t_blog
where status = 1 and (author like ?)
and (publish_time between ? and ?)
order by publish_time asc

原文链接:https://www.cnblogs.com/summerday152/p/14182138.html

如果觉得本文对你有帮助,可以关注一下我公众号,回复关键字【面试】即可得到一份Java核心知识点整理与一份面试大礼包!另有更多技术干货文章以及相关资料共享,大家一起学习进步!

版权声明
本文为[wx60c1a9177952c]所创,转载请带上原文链接,感谢
https://blog.51cto.com/u_15265637/2894644

  1. Netty源码解析-概述篇
  2. Netty源码解析-概述篇
  3. Netty源码解析1-Buffer
  4. Netty源码解析1-Buffer
  5. Netty源码解析2-Reactor
  6. Netty源码解析2-Reactor
  7. Netty源码解析3-Pipeline
  8. Netty源码解析3-Pipeline
  9. Netty源码解析4-Handler综述
  10. Netty源码解析4-Handler综述
  11. Netty源码解析5-ChannelHandler
  12. Netty源码解析5-ChannelHandler
  13. Netty源码解析6-ChannelHandler实例之LoggingHandler
  14. Netty源码解析6-ChannelHandler实例之LoggingHandler
  15. Netty源码解析7-ChannelHandler实例之TimeoutHandler
  16. Netty源码解析7-ChannelHandler实例之TimeoutHandler
  17. Netty源码解析8-ChannelHandler实例之CodecHandler
  18. Netty源码解析8-ChannelHandler实例之CodecHandler
  19. Netty源码解析9-ChannelHandler实例之MessageToByteEncoder
  20. Netty源码解析9-ChannelHandler实例之MessageToByteEncoder
  21. 大数据面试题之Hbase系列
  22. 你可能需要的Kafka面试题与答案整理
  23. 你可能需要的Kafka面试题与答案整理
  24. 后起之秀Pulsar VS. 传统强者Kafka?谁更强
  25. 后起之秀Pulsar VS. 传统强者Kafka?谁更强
  26. 【大数据哔哔集20210123】别问,问就是Kafka最可靠
  27. 【大数据哔哔集20210123】别问,问就是Kafka最可靠
  28. 【大数据哔哔集20210124】有人问我Kafka Leader选举?我真没慌
  29. 【大数据哔哔集20210124】有人问我Kafka Leader选举?我真没慌
  30. 【大数据哔哔集20210117】Kafka 的高可靠性是怎么实现的
  31. 【大数据哔哔集20210117】Kafka 的高可靠性是怎么实现的
  32. Kafka Connect | 无缝结合Kafka构建高效ETL方案
  33. Kafka面试题总结(一)
  34. Kafka面试题总结(一)
  35. Kafka面试题整理(二)
  36. Kafka面试题整理(二)
  37. 基于Kafka Flink Redis的电商大屏实时计算案例
  38. 基于Kafka Flink Redis的电商大屏实时计算案例
  39. Google布隆过滤器与Redis布隆过滤器详解
  40. Google布隆过滤器与Redis布隆过滤器详解
  41. 【Java Web前端开发】前端框架 bootstrap+jquery+angularjs探索
  42. 关于Redis的几件小事 | 高并发和高可用
  43. 关于Redis的几件小事 | 高并发和高可用
  44. 关于redis的几件小事(一)redis的使用目的与问题
  45. 关于redis的几件小事(一)redis的使用目的与问题
  46. 阿里云Redis技术架构演进
  47. 阿里云Redis技术架构演进
  48. 阿里云Redis技术架构演进
  49. Flink实战(109):connector(十八)hdfs 读写(三)StreamingFileSink相关特性及代码实战
  50. Flink实战(110):flink-sql使用(十八)connector(十九)Flink 与 hive 结合使用(七) Flink Hive Connector 使用
  51. Flink实战(110):flink-sql使用(十八)connector(十九)Flink 与 hive 结合使用(七) Flink Hive Connector 使用
  52. Flink实战(111):flink-sql使用(十九)Flink 与 hive 结合使用(八)Hive Streaming 实战解析
  53. Flink实战(111):flink-sql使用(十九)Flink 与 hive 结合使用(八)Hive Streaming 实战解析
  54. Docker常用命令,这些都要会!
  55. 鸟哥的Linux私房菜学习之第九章笔记
  56. Java NIO之Channel(通道)
  57. Java NIO之拥抱Path和Files
  58. Redis changed its open source license, and many projects were no longer open source
  59. JDK 11 has entered the candidate release stage, and the official version is planned to be released on September 25
  60. [* *] the latest version of windows 10 hides Linux?