1、引入querydsl

1.1、导包

  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.1.4.RELEASE</version>
  5. </parent>
  6. <dependencies>
  7. <!-- querydsl -->
  8. <dependency>
  9. <groupId>com.querydsl</groupId>
  10. <artifactId>querydsl-jpa</artifactId>
  11. </dependency>
  12. <dependency>
  13. <groupId>com.querydsl</groupId>
  14. <artifactId>querydsl-apt</artifactId>
  15. <scope>provided</scope>
  16. </dependency>
  17. </dependencies>

1.2、添加插件

  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>com.mysema.maven</groupId>
  5. <artifactId>apt-maven-plugin</artifactId>
  6. <version>1.1.3</version>
  7. <executions>
  8. <execution>
  9. <goals>
  10. <goal>process</goal>
  11. </goals>
  12. <configuration>
  13. <outputDirectory>target/generated-sources/java</outputDirectory>
  14. <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
  15. </configuration>
  16. </execution>
  17. </executions>
  18. </plugin>
  19. </plugins>
  20. </build>

插件的作用是把带有@Entity注解的实体类在指定路径target/generated-sources/java下生成一个衍生的实体类,我们后面就是用这个衍生出来的实体类去构建动态查询的条件进行动态查询。

1.3、注入bean

  1. @Bean
  2. public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
  3. return new JPAQueryFactory(entityManager);
  4. }

2、创建实体类

  1. @Entity
  2. @Table(name = "actor")
  3. @Data
  4. public class Actor {
  5. /**
  6. * 主键生成采用数据库自增方式,比如MySQLAUTO_INCREMENT
  7. */
  8. @Id
  9. @GeneratedValue(strategy = GenerationType.IDENTITY)
  10. private Long id;
  11. @Column(name = "actor_name", nullable = false, length = 128, unique = true)
  12. private String actorName;
  13. @Column(name = "actor_age", nullable = false)
  14. private int actorAge;
  15. @Column(name = "actor_email", length = 64, unique = true)
  16. private String actorEmail;
  17. @Column(name = "create_time", nullable = false, length = 32)
  18. private String createTime = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss SSS");
  19. }

如果是IDEA工具,执行Maven插件的compile就能在指定目录生成QActor类。
image.png
如果是Eclipse,右键项目工程,执行maven的update操作就可以在指定目录中生成实体类。

3、创建Repository

需要继承 QuerydslPredicateExecutor

  1. public interface QuerydslRepository extends JpaRepository<Actor, Long>, QuerydslPredicateExecutor<Actor> {
  2. }

4、使用QueryDSL

4.1、原生dsl查询

4.1.1、直接根据条件查询
  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. @Slf4j
  4. public class QuerydslTest {
  5. @Autowired
  6. private JPAQueryFactory jpaQueryFactory;
  7. /**
  8. * 直接根据条件查询
  9. */
  10. @Test
  11. public void testFindByActorNameAndActorEmail() {
  12. QActor qActor = QActor.actor;
  13. Actor actor = jpaQueryFactory.selectFrom(qActor)
  14. .where(
  15. qActor.actorName.eq("高庸涵"),
  16. qActor.actorEmail.eq("123456789@qq.com")
  17. )
  18. .fetchOne();
  19. log.info(JSONUtil.toJsonPrettyStr(actor));
  20. }
  21. }

4.1.2、查询所有并根据字段排序
  1. /**
  2. * 查询所有并根据字段排序
  3. */
  4. @Test
  5. public void testFindAll() {
  6. QActor qActor = QActor.actor;
  7. List<Actor> actorList = jpaQueryFactory.selectFrom(qActor)
  8. .orderBy(
  9. qActor.actorAge.asc()
  10. )
  11. .fetch();
  12. log.info(JSONUtil.toJsonPrettyStr(actorList));
  13. }

4.1.3、分页查询,并根据字段排序
  1. /**
  2. * 分页查询,并根据字段排序
  3. */
  4. @Test
  5. public void testFindByPagination() {
  6. int page = 0; // 第几页
  7. int pageSize = 10; // 每页大小
  8. QActor qActor = QActor.actor;
  9. QueryResults<Actor> actorQueryResults = jpaQueryFactory.selectFrom(qActor)
  10. .orderBy(
  11. qActor.actorAge.asc()
  12. )
  13. .offset(page)
  14. .limit(pageSize)
  15. .fetchResults();
  16. // 获取分页参数
  17. long total = actorQueryResults.getTotal();
  18. long totalPage = (total % pageSize == 0) ? (total / pageSize) : (total / pageSize + 1);
  19. log.info("分页查询第:[{}]页,pageSize:[{}],共有:[{}]数据,共有:[{}]页", page, pageSize, total, totalPage);
  20. List<Actor> actorListByPagination = actorQueryResults.getResults();
  21. log.info(JSONUtil.toJsonPrettyStr(actorListByPagination));
  22. }

4.1.4、根据条件模糊查询,并指定某个字段的范围
  1. /**
  2. * 根据条件模糊查询,并指定某个字段的范围
  3. */
  4. @Test
  5. public void testFindByLikeNameAndEmailAndBetweenAgeOrderById() {
  6. QActor qActor = QActor.actor;
  7. List<Actor> actorList = jpaQueryFactory.selectFrom(qActor)
  8. .where(
  9. qActor.actorName.like("name%"),
  10. qActor.actorEmail.like("email%"),
  11. qActor.actorAge.between(20, 50)
  12. )
  13. .orderBy(
  14. qActor.id.asc()
  15. )
  16. .fetch();
  17. log.info(JSONUtil.toJsonPrettyStr(actorList));
  18. }

4.2、jpa整合dsl查询

4.2.1、模糊查询并分页排序
  1. @Autowired
  2. private QuerydslRepository querydslRepository;
  3. /**
  4. * 模糊查询并分页排序
  5. */
  6. @Test
  7. public void testFindByActorNameAndActorEmailPagination() {
  8. int page = 0; // 第几页
  9. int pageSize = 10; // 每页大小
  10. QActor qActor = QActor.actor;
  11. // 模糊查询条件
  12. BooleanExpression expression = qActor.actorName.like("name%").and(qActor.actorEmail.like("email%"));
  13. // 排序、分页参数
  14. Sort sort = new Sort(Sort.Direction.DESC, "actorAge");
  15. PageRequest pageRequest = PageRequest.of(page < 0 ? 0 : page, pageSize, sort);
  16. Page<Actor> actorPage = querydslRepository.findAll(expression, pageRequest);
  17. log.info("分页查询第:[{}]页,pageSize:[{}],共有:[{}]数据,共有:[{}]页", page, pageSize, actorPage.getTotalElements(), actorPage.getTotalPages());
  18. List<Actor> actorListByPagination = actorPage.getContent();
  19. log.info(JSONUtil.toJsonPrettyStr(actorListByPagination));
  20. }

4.2.2、动态查询并分页排序
  1. /**
  2. * 动态查询并分页排序
  3. */
  4. @Test
  5. public void testFindByDynamicQuery() {
  6. Integer actorAge = 45;
  7. String actorEmail = "email";
  8. String actorName = null;
  9. String createTime = "2020-11-21";
  10. int page = 0; // 第几页
  11. int pageSize = 10; // 每页大小
  12. QActor qActor = QActor.actor;
  13. // 初始化组装条件(类似where 1=1)
  14. Predicate predicate = qActor.isNotNull().or(qActor.isNull());
  15. //执行动态条件拼装
  16. // 相等
  17. predicate = actorAge == null ? predicate : ExpressionUtils.and(predicate, qActor.actorAge.eq(actorAge));
  18. // like 模糊匹配
  19. predicate = actorEmail == null ? predicate : ExpressionUtils.and(predicate, qActor.actorEmail.like(actorEmail + "%"));
  20. predicate = actorName == null ? predicate : ExpressionUtils.and(predicate, qActor.actorName.like(actorName + "%"));
  21. // 包含,相当于like %xxx%
  22. predicate = createTime == null ? predicate : ExpressionUtils.and(predicate, qActor.createTime.contains(createTime));
  23. // 排序、分页参数
  24. Sort sort = new Sort(Sort.Direction.ASC, "id");
  25. PageRequest pageRequest = PageRequest.of(page < 0 ? 0 : page, pageSize, sort);
  26. Page<Actor> actorPage = querydslRepository.findAll(predicate, pageRequest);
  27. log.info("分页查询第:[{}]页,pageSize:[{}],共有:[{}]数据,共有:[{}]页", page, pageSize, actorPage.getTotalElements(), actorPage.getTotalPages());
  28. List<Actor> actorListByPagination = actorPage.getContent();
  29. log.info(JSONUtil.toJsonPrettyStr(actorListByPagination));
  30. }

代码地址