其他分享
首页 > 其他分享> > QueryDSL

QueryDSL

作者:互联网

QueryDSL

简介

  1. QueryDSL仅仅是一个通用的查询框架,专注于通过Java API构建类型安全的SQL查询。
  2. Querydsl可以通过一组通用的查询API为用户构建出适合不同类型ORM框架或者是SQL的查询语句,也就是说QueryDSL是基于各种ORM框架以及SQL之上的一个通用的查询框架。
  3. 借助QueryDSL可以在任何支持的ORM框架或者SQL平台上以一种通用的API方式来构建查询。目前QueryDSL支持的平台包括JPA,JDO,SQL,Java Collections,Mongodb,Lucene
  4. 官网地址:点击进入
  5. github地址:点击进入

p6spy

优点

原理

P6Spy通过劫持JDBC驱动,在调用实际JDBC驱动前拦截调用的目标语,达到SQL语句日志记录的目的

应用

配置到项目

1、引入querydsl

  1. 导包,不需要携带版本号,springboot已经集成

    <!--query dsl-->
    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-apt</artifactId>
        <scope>provided</scope>
    </dependency>
    <!--query dsl end-->
    
    <!-- jpa -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- jpa end -->
    
    <!-- sql打印 -->
    <dependency>
        <groupId>p6spy</groupId>
        <artifactId>p6spy</artifactId>
        <version>3.8.5</version>
    </dependency>
    <!-- sql打印 end -->
    
  2. 加入插件,让程序自动生成query type(查询实体,命名方式为:“Q”+对应实体名)。

    <!--该插件可以生成querysdl需要的查询对象,执行mvn compile即可-->
    <plugin>
        <groupId>com.mysema.maven</groupId>
        <artifactId>apt-maven-plugin</artifactId>
        <version>1.1.3</version>
        <executions>
            <execution>
                <goals>
                    <goal>process</goal>
                </goals>
                <configuration>
                    <outputDirectory>target/generated-sources/java</outputDirectory>
                    <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
                </configuration>
            </execution>
        </executions>
    </plugin>
    

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

  3. 注入bean

    import com.querydsl.jpa.impl.JPAQueryFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import javax.persistence.EntityManager;
    
    /**
     * @auther YangFan
     * @Date 2021/3/25 9:14
     */
    @Configuration
    public class JPAFactory {
        @Bean
        public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
            return new JPAQueryFactory(entityManager);
        }
    }
    

2、配置文件

3、创建实体类

Actor

@Entity
@Table(name = "actor")
@Data
public class Actor {

    /**
     * 主键生成采用数据库自增方式,比如MySQL的AUTO_INCREMENT
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "actor_name", nullable = false, length = 128, unique = true)
    private String actorName;

    @Column(name = "actor_age", nullable = false)
    private int actorAge;

    @Column(name = "actor_email", length = 64, unique = true)
    private String actorEmail;

    @Column(name = "create_time", nullable = false, length = 32)
    private String createTime = LocalDateTime.now().toString();
}

Work

@Entity
@Table(name = "work")
@Data
public class Work {

    /**
     * 主键生成采用数据库自增方式,比如MySQL的AUTO_INCREMENT
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "word_name", nullable = false, length = 128)
    private String workName;
}

执行Maven插件的compile就能在指定目录生成QActor类和QWork类。

4、创建Repository

需要继承 QuerydslPredicateExecutor

public interface QuerydslRepository extends JpaRepository<Actor, Long>, QuerydslPredicateExecutor<Actor> {

}

5、使用QueryDSL

5.1、原生dsl查询

  1. 直接根据条件查询

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Slf4j
    public class QuerydslTest {
        @Autowired
        private JPAQueryFactory jpaQueryFactory;
        
        ObjectMapper mapper = new ObjectMapper();
    
        /**
         * 直接根据条件查询
         */
        @Test
        public void testFindByActorNameAndActorEmail() {
            QActor qActor = QActor.actor;
            Actor actor = jpaQueryFactory.selectFrom(qActor)
                    .where(
                            qActor.actorName.eq("嘀嘀嘀"),
                            qActor.actorEmail.eq("123456789@qq.com")
                    )
                    .fetchOne();
            try {
                String s = mapper.writeValueAsString(actor);
                log.info("s: {}", s);
            } catch (JsonProcessingException e) {
    
            }
        }
    }
    
  2. 查询所有并根据字段排序

    /**
     * 查询所有并根据字段排序
     */
    @Test
    public void testFindAll() {
        	QActor qActor = QActor.actor;
            List<Actor> actorList = jpaQueryFactory.selectFrom(qActor)
                    .orderBy(
                            qActor.actorAge.asc()
                    )
                    .fetch();
            try {
                String s = mapper.writeValueAsString(actorList);
                log.info("s: {}", s);
            } catch (JsonProcessingException e) {
    
            }
    }
    
  3. 分页查询,并根据字段排序

    /**
     * 分页查询,并根据字段排序
     */
    @Test
    public void testFindByPagination() {
        	int page = 0; // 第几页
            int pageSize = 10; // 每页大小
    
            QActor qActor = QActor.actor;
            QueryResults<Actor> actorQueryResults = jpaQueryFactory.selectFrom(qActor)
                    .orderBy(
                            qActor.actorAge.asc()
                    )
                    .offset(page)
                    .limit(pageSize)
                    .fetchResults();
            // 获取分页参数
            long total = actorQueryResults.getTotal();
            long totalPage = (total % pageSize == 0) ? (total / pageSize) : (total / pageSize + 1);
            log.info("分页查询第:[{}]页,pageSize:[{}],共有:[{}]数据,共有:[{}]页", page, pageSize, total, totalPage);
            List<Actor> actorListByPagination = actorQueryResults.getResults();
            try {
                String s = mapper.writeValueAsString(actorListByPagination);
                log.info("s: {}", s);
            } catch (JsonProcessingException e) {
    
            }
    }
    
  4. 根据条件模糊查询,并指定某个字段的范围

    /**
     * 根据条件模糊查询,并指定某个字段的范围
     */
    @Test
    public void testFindByLikeNameAndEmailAndBetweenAgeOrderById() {
        	QActor qActor = QActor.actor;
            List<Actor> actorList = jpaQueryFactory.selectFrom(qActor)
                    .where(
                            qActor.actorName.like("name%"),
                            qActor.actorEmail.like("email%"),
                            qActor.actorAge.between(20, 50)
                    )
                    .orderBy(
                            qActor.id.asc()
                    )
                    .fetch();
            try {
                String s = mapper.writeValueAsString(actorList);
                log.info("s: {}", s);
            } catch (JsonProcessingException e) {
    
            }
    }
    
  5. 两张表关联查询

    /**
      * 两张表关联查询
      */
    @Test
    public void testTwoTablesQuery() {
        QActor qActor = QActor.actor;
        QWork work = QWork.work;
    
        List<Tuple> fetch = jpaQueryFactory.select(qActor.id,qActor.actorName,qActor.actorAge,work.workName).from(qActor).leftJoin(work).on(qActor.id.eq(work.id)).orderBy(qActor.actorAge.desc()).fetch();
        System.err.println(fetch);
    }
    
  6. 两张表关联查询将结果封装至vo中

    /**
     * 查询并将结果封装至vo中
     */
    @Test
    public void testFindTwoTableToVo() {
        QActor qActor = QActor.actor;
        QWork work = QWork.work;
        List<ActorInfoVO> fetch = jpaQueryFactory.select(Projections.bean(ActorInfoVO.class, qActor.id, qActor.actorName, work.workName)).from(qActor).leftJoin(work).on(qActor.id.eq(work.id)).fetch();
        System.err.println(fetch);
    }
    

5.2、jpa整合dsl查询

  1. 模糊查询并分页排序

    @Autowired
    private QuerydslRepository querydslRepository;
    
    /**
     * 模糊查询并分页排序
     */
    @Test
    public void testFindByActorNameAndActorEmailPagination() {
        	int page = 0; // 第几页
            int pageSize = 10; // 每页大小
    
            QActor qActor = QActor.actor;
            // 模糊查询条件
            BooleanExpression expression = qActor.actorName.like("name%").and(qActor.actorEmail.like("email%"));
            // 排序、分页参数
            Sort sort = new Sort(Sort.Direction.DESC, "actorAge");
            PageRequest pageRequest = PageRequest.of(page < 0 ? 0 : page, pageSize, sort);
            Page<Actor> actorPage = querydslRepository.findAll(expression, pageRequest);
            log.info("分页查询第:[{}]页,pageSize:[{}],共有:[{}]数据,共有:[{}]页", page, pageSize, actorPage.getTotalElements(), actorPage.getTotalPages());
            List<Actor> actorListByPagination = actorPage.getContent();
            try {
                String s = mapper.writeValueAsString(actorListByPagination);
                log.info("s: {}", s);
            } catch (JsonProcessingException e) {
    
            }
    }
    
  2. 动态查询并分页排序

    /**
     * 动态查询并分页排序
     */
    @Test
    public void testFindByDynamicQuery() {
        	Integer actorAge = 45;
            String actorEmail = "email";
            String actorName = null;
            String createTime = "2020-11-21";
    
            int page = 0; // 第几页
            int pageSize = 10; // 每页大小
    
            QActor qActor = QActor.actor;
            // 初始化组装条件(类似where 1=1)
            Predicate predicate = qActor.isNotNull().or(qActor.isNull());
    
            //执行动态条件拼装
            // 相等
            predicate = actorAge == null ? predicate : ExpressionUtils.and(predicate, qActor.actorAge.eq(actorAge));
            // like 模糊匹配
            predicate = actorEmail == null ? predicate : ExpressionUtils.and(predicate, qActor.actorEmail.like(actorEmail + "%"));
            predicate = actorName == null ? predicate : ExpressionUtils.and(predicate, qActor.actorName.like(actorName + "%"));
    
            // 排序、分页参数
            Sort sort = new Sort(Sort.Direction.ASC, "id");
            PageRequest pageRequest = PageRequest.of(page < 0 ? 0 : page, pageSize, sort);
            Page<Actor> actorPage = querydslRepository.findAll(predicate, pageRequest);
            log.info("分页查询第:[{}]页,pageSize:[{}],共有:[{}]数据,共有:[{}]页", page, pageSize, actorPage.getTotalElements(), actorPage.getTotalPages());
            List<Actor> actorListByPagination = actorPage.getContent();
            try {
                String s = mapper.writeValueAsString(actorListByPagination);
                log.info("s: {}", s);
            } catch (JsonProcessingException e) {
    
            }
    }
    

5.3、删除和修改

删除和修改需要添加@Transactional

  1. 修改

    /**
     * 修改
     *
     * 需要添加@Transactional,否则报错
     */
    @Transactional
    @Test
    public void testUpdate() {
        QWork work = QWork.work;
        long update = jpaQueryFactory.update(work).set(work.workName, "修改了之后的作品").where(work.id.eq(2l)).execute();
        System.err.println("update成功的条数" + update);
    }
    
  2. 删除

    /**
     * 删除
     *
     * 需要添加@Transactional,否则报错
     */
    @Transactional
    @Test
    public void testDelete() {
        QWork work = QWork.work;
        long deleted = jpaQueryFactory.delete(work).where(work.id.eq(2l)).execute();
        System.err.println("delete成功的条数" + deleted);
    }
    

标签:String,work,QueryDSL,查询,com,public,qActor
来源: https://blog.csdn.net/yanzhenjingfan/article/details/115295079