• JPA 复杂查询


     添加依赖

        <!--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>  


        <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, 将生成Query实体。

    单表查询

    package com.chhliu.springboot.jpa.repository;
    
    import java.util.List;
    
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import javax.persistence.Query;
    import javax.transaction.Transactional;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Sort;
    import org.springframework.stereotype.Component;
    
    import com.chhliu.springboot.jpa.entity.QUser;
    import com.chhliu.springboot.jpa.entity.User;
    import com.querydsl.core.types.Predicate;
    import com.querydsl.jpa.impl.JPAQueryFactory;
    
    /**
     * 描述:QueryDSL JPA
     * @author chhliu
     */
    @Component
    @Transactional
    public class UserRepositoryManagerDsl {
        @Autowired
        private UserRepositoryDls repository;
        
        @Autowired
        @PersistenceContext
        private EntityManager entityManager;
    
            private JPAQueryFactory queryFactory;
        
         @PostConstruct
         public void init() {
            queryFactory = new JPAQueryFactory(entityManager);
         }
    
           public User findUserByUserName(final String userName){
             /**
             * 该例是使用spring data QueryDSL实现
             */
            QUser quser = QUser.user;
            Predicate predicate = quser.name.eq(userName);
            return repository.findOne(predicate);
        }
        
        /**
         * attention:
         * Details:查询user表中的所有记录
         */
        public List<User> findAll(){
            QUser quser = QUser.user;
            return queryFactory.selectFrom(quser)
                        .fetch();
        }
        
        /**
         * Details:单条件查询
         */
        public User findOneByUserName(final String userName){
            QUser quser = QUser.user;
            return queryFactory.selectFrom(quser)
                .where(quser.name.eq(userName))
                .fetchOne();
        }
        
        /**
         * Details:单表多条件查询
         */
        public User findOneByUserNameAndAddress(final String userName, final String address){
            QUser quser = QUser.user;
            return queryFactory.select(quser)
                .from(quser) // 上面两句代码等价与selectFrom
                .where(quser.name.eq(userName).and(quser.address.eq(address)))// 这句代码等同于where(quser.name.eq(userName), quser.address.eq(address))
                .fetchOne();
        }
        
        /**
         * Details:使用join查询
         */
        public List<User> findUsersByJoin(){
            QUser quser = QUser.user;
            QUser userName = new QUser("name");
            return queryFactory.selectFrom(quser)
                .innerJoin(quser)
                .on(quser.id.intValue().eq(userName.id.intValue()))
                .fetch();
        }
        
        /**
         * Details:将查询结果排序
         */
        public List<User> findUserAndOrder(){
            QUser quser = QUser.user;
            return queryFactory.selectFrom(quser)
                .orderBy(quser.id.desc())
                .fetch();
        }
        
        /**
         * Details:Group By使用
         */
        public List<String> findUserByGroup(){
            QUser quser = QUser.user;
            return queryFactory.select(quser.name)
                        .from(quser)
                        .groupBy(quser.name)
                        .fetch();
        }
        
        /**
         * Details:删除用户
         */
        public long deleteUser(String userName){
            QUser quser = QUser.user;
            return queryFactory.delete(quser).where(quser.name.eq(userName)).execute();
        }
        
        /**
         * Details:更新记录
         */
        public long updateUser(final User u, final String userName){
            QUser quser = QUser.user;
            return queryFactory.update(quser).where(quser.name.eq(userName))
                .set(quser.name, u.getName())
                .set(quser.age, u.getAge())
                .set(quser.address, u.getAddress())
                .execute();
        }
        
        /**
         * Details:使用原生Query
         */
        public User findOneUserByOriginalSql(final String userName){
            QUser quser = QUser.user;
            Query query = queryFactory.selectFrom(quser)
                    .where(quser.name.eq(userName)).createQuery();
            return (User) query.getSingleResult();
        }
        
        /**
         * Details:分页查询单表
         */
        public Page<User> findAllAndPager(final int offset, final int pageSize){
            Predicate predicate = QUser.user.id.lt(10);
            Sort sort = new Sort(new Sort.Order(Sort.Direction.DESC, "id"));
            PageRequest pr = new PageRequest(offset, pageSize, sort);
            return repository.findAll(predicate, pr);
        }
    }

    多表操作示例(一对一)

    package com.chhliu.springboot.jpa.repository;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.annotation.PostConstruct;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import com.chhliu.springboot.jpa.dto.PersonIDCardDto;
    import com.chhliu.springboot.jpa.entity.QIDCard;
    import com.chhliu.springboot.jpa.entity.QPerson;
    import com.querydsl.core.QueryResults;
    import com.querydsl.core.Tuple;
    import com.querydsl.core.types.Predicate;
    import com.querydsl.jpa.impl.JPAQuery;
    import com.querydsl.jpa.impl.JPAQueryFactory;
    
    @Component
    public class PersonAndIDCardManager {
        @Autowired
        @PersistenceContext
        private EntityManager entityManager;
        
        private JPAQueryFactory queryFactory;
        
        @PostConstruct
        public void init() {
            queryFactory = new JPAQueryFactory(entityManager);
        }
        
        /**
         * Details:多表动态查询
         */
        public List<Tuple> findAllPersonAndIdCard(){
            Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
            JPAQuery<Tuple> jpaQuery = queryFactory.select(QIDCard.iDCard.idNo, QPerson.person.address, QPerson.person.name)
                    .from(QIDCard.iDCard, QPerson.person)
                    .where(predicate);
            return jpaQuery.fetch();
        }
        
        /**
         * Details:将查询结果以DTO的方式输出
         */
        public List<PersonIDCardDto> findByDTO(){
            Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
            JPAQuery<Tuple> jpaQuery = queryFactory.select(QIDCard.iDCard.idNo, QPerson.person.address, QPerson.person.name)
                    .from(QIDCard.iDCard, QPerson.person)
                    .where(predicate);
            List<Tuple> tuples = jpaQuery.fetch();
            List<PersonIDCardDto> dtos = new ArrayList<PersonIDCardDto>();
            if(null != tuples && !tuples.isEmpty()){
                for(Tuple tuple:tuples){
                    String address = tuple.get(QPerson.person.address);
                    String name = tuple.get(QPerson.person.name);
                    String idCard = tuple.get(QIDCard.iDCard.idNo);
                    PersonIDCardDto dto = new PersonIDCardDto();
                    dto.setAddress(address);
                    dto.setIdNo(idCard);
                    dto.setName(name);
                    dtos.add(dto);
                }
            }
            return dtos;
        }
        
        /**
         * Details:多表动态查询,并分页
         */
        public QueryResults<Tuple> findByDtoAndPager(int offset, int pageSize){
            Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
            return queryFactory.select(QIDCard.iDCard.idNo, QPerson.person.address, QPerson.person.name)
                    .from(QIDCard.iDCard, QPerson.person)
                    .where(predicate)
                    .offset(offset)
                    .limit(pageSize)
                    .fetchResults();
        }
    }

    上面将查询结果以DTO的方式输出的示例中,在查询结束后,将查询结果手动的转换成了DTO对象,这种方式其实不太优雅,QueryDSL给我们提供了更好的方式,见下面的示例:

    /**
         * Details:方式一:使用Bean投影
         */
        public List<PersonIDCardDto> findByDTOUseBean(){
            Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
            return queryFactory.select(
                    Projections.bean(PersonIDCardDto.class, QIDCard.iDCard.idNo, QPerson.person.address, QPerson.person.name))
                    .from(QIDCard.iDCard, QPerson.person)
                    .where(predicate)
                    .fetch();
        }
        
        /**
         * Details:方式二:使用fields来代替setter
         */
        public List<PersonIDCardDto> findByDTOUseFields(){
            Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
            return queryFactory.select(
                    Projections.fields(PersonIDCardDto.class, QIDCard.iDCard.idNo, QPerson.person.address, QPerson.person.name))
                    .from(QIDCard.iDCard, QPerson.person)
                    .where(predicate)
                    .fetch();
        }
        
        /**
         * Details:方式三:使用构造方法,注意构造方法中属性的顺序必须和构造器中的顺序一致
         */
        public List<PersonIDCardDto> findByDTOUseConstructor(){
            Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
            return queryFactory.select(
                    Projections.constructor(PersonIDCardDto.class, QPerson.person.name, QPerson.person.address, QIDCard.iDCard.idNo))
                    .from(QIDCard.iDCard, QPerson.person)
                    .where(predicate)
                    .fetch();
        }

    上面只是提供了几种思路,当然,还可以使用@QueryProjection来实现,非常灵活。
    一对多示例:

    package com.chhliu.springboot.jpa.repository;
    
    import java.util.List;
    
    import javax.annotation.PostConstruct;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import com.chhliu.springboot.jpa.entity.QOrder;
    import com.chhliu.springboot.jpa.entity.QOrderItem;
    import com.querydsl.core.Tuple;
    import com.querydsl.core.types.Predicate;
    import com.querydsl.jpa.impl.JPAQuery;
    import com.querydsl.jpa.impl.JPAQueryFactory;
    
    @Component
    public class OrderAndOrderItemManager {
        
        @Autowired
        @PersistenceContext
        private EntityManager entityManager;
        
        private JPAQueryFactory queryFactory;
        
        @PostConstruct
        public void init() {
            queryFactory = new JPAQueryFactory(entityManager);
        }
        
        /**
         * Details:一对多,条件查询
         */
        public List<Tuple> findOrderAndOrderItemByOrderName(String orderName){
            //添加查询条件
            Predicate predicate = QOrder.order.orderName.eq(orderName);
            JPAQuery<Tuple> jpaQuery = queryFactory.select(QOrder.order, QOrderItem.orderItem)
                                            .from(QOrder.order, QOrderItem.orderItem)
                                            .where(QOrderItem.orderItem.order.id.intValue().eq(QOrder.order.id.intValue()), predicate);
            
            //拿到结果
            return jpaQuery.fetch();
        }
        
        /**
         * Details:多表连接查询
         */
        public List<Tuple> findAllByOrderName(String orderName){
            //添加查询条件
            Predicate predicate = QOrder.order.orderName.eq(orderName);
            JPAQuery<Tuple> jpaQuery = queryFactory.select(QOrder.order, QOrderItem.orderItem)
                                            .from(QOrder.order, QOrderItem.orderItem)
                                            .rightJoin(QOrder.order)
                                            .on(QOrderItem.orderItem.order.id.intValue().eq(QOrder.order.id.intValue()));
            jpaQuery.where(predicate);
            //拿到结果
            return jpaQuery.fetch();
        }
    }

    链接

    Querydsl Reference Guide

    使用QueryDSL

    复杂查询的封装

    spring boot-jpa整合QueryDSL来简化复杂操作

    Spring Boot JPA - 使用 Querydsl 处理复杂的操作

  • 相关阅读:
    一句话说说java设计模式
    说说JVM中的操作码
    说说javap命令
    java中的类加载器
    浅谈幂等
    InstallShield Limited Edition for Visual Studio 国内注册时国家无下拉框解决方法
    Winform程序部署方式总结二——Windows Installer发布
    Winform程序部署方式总结一——ClickOnce发布
    WebService部署服务器调试时提示 “测试窗体只能用于来自本地计算机的请求”解决方法
    MVC绕过登陆界面验证时HttpContext.Current.User.Identity.Name取值为空问题解决方法
  • 原文地址:https://www.cnblogs.com/tonyq/p/7881142.html
Copyright © 2020-2023  润新知