spring data jpa 1.9/1.10 复杂sql分页查询

基于jpa

controller中创建Pageable实现类PageRequest

PageRequest pageRequest = new PageRequest(page, size,new Sort(Sort.Direction.DESC, "update_time") );//

dao代码如下

public interface DataNodeDao extends PagingAndSortingRepository<TDataNode, Long> {
    @Query(value = "SELECT dn.* FROM data_node dn LEFT JOIN data_device_rel ddr ON dn.id = ddr.data_id LEFT JOIN device_station_rel dsr ON ddr.device_id = dsr.device_id LEFT JOIN user_station us ON dsr.station_id = us.station_id WHERE us.organization_id = ?1  AND dn.STATUS = ?2  /*#pageable*/",
            countQuery = "SELECT count(dn.id) FROM data_node dn LEFT JOIN data_device_rel ddr ON dn.id = ddr.data_id LEFT JOIN device_station_rel dsr ON ddr.device_id = dsr.device_id LEFT JOIN user_station us ON dsr.station_id = us.station_id WHERE us.organization_id = ?1 AND dn.STATUS = ?2 ",nativeQuery = true)
    Page<TDataNode> userDataNodeList(int organizationId, int status, Pageable page);
    @Query("select dn from TDataNode dn where  dn.status=?1")
    Page<TDataNode> userDataNodeList(int status, Pageable page);

第一种使用nativeQuery,需要加上#pageable,不然会报错,spring源码如下,如果要使用分页,必须包含#pageable或者#sort

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.data.jpa.repository.query;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.springframework.data.repository.query.EvaluationContextProvider;
import org.springframework.data.repository.query.Parameters;
import org.springframework.expression.spel.standard.SpelExpressionParser;

final class NativeJpaQuery extends AbstractStringBasedJpaQuery {
    public NativeJpaQuery(JpaQueryMethod method, EntityManager em, String queryString, EvaluationContextProvider evaluationContextProvider, SpelExpressionParser parser) {
        super(method, em, queryString, evaluationContextProvider, parser);
        Parameters<?, ?> parameters = method.getParameters();
        boolean hasPagingOrSortingParameter = parameters.hasPageableParameter() || parameters.hasSortParameter();
        boolean containsPageableOrSortInQueryExpression = queryString.contains("#pageable") || queryString.contains("#sort");
        if (hasPagingOrSortingParameter && !containsPageableOrSortInQueryExpression) {
            throw new InvalidJpaQueryMethodException("Cannot use native queries with dynamic sorting and/or pagination in method " + method);
        }
    }

    protected Query createJpaQuery(String queryString) {
        return this.getQueryMethod().isQueryForEntity() ? this.getEntityManager().createNativeQuery(queryString, this.getQueryMethod().getReturnedObjectType()) : this.getEntityManager().createNativeQuery(queryString);
    }
}

如果使用第二种hql,则不用做额外处理

最终jpa会在sql末尾自动拼接
order by dn.update_time desc limit **

官网文档
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/

基于JdbcTemplate

jpa的动态条件查询Specification太复杂,可读性比较差,还不如直接用jdbcTemplate,封装的类如下

package common.util;

import org.springframework.core.convert.converter.Converter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.util.Iterator;
import java.util.List;

/**
 * Created by wmf on 2017/5/23.
 */
public class JPAPageUtils<T> {

    public  Page<T> getPage(RowMapper<T> mapper, JdbcTemplate jt, String sql, int currentPage, int pageSize){
        int totalRows = jt.queryForObject("select count(*) from ("+sql+") t9", Integer.class);
        int total;
        // 总行数 % 每页行数 = 0
        if (totalRows % pageSize == 0) {
            total= totalRows / pageSize;
        } else {
            // 总行数 % 每页行数 != 0
            total= totalRows / pageSize + 1;
        }
        List<T> list = jt.query("select t9.* from ("+sql+") t9 limit ?,?",
                new Object[]{(currentPage * pageSize), pageSize},mapper);
        Page<T> result= new Page<T>() {
            @Override
            public Iterator<T> iterator() {
                return null;
            }

            @Override
            public int getTotalPages() {
                return total;
            }

            @Override
            public long getTotalElements() {
                return totalRows;
            }

            @Override
            public int getNumber() {
                return currentPage;
            }

            @Override
            public int getSize() {
                return pageSize;
            }

            @Override
            public int getNumberOfElements() {
                return 0;
            }

            @Override
            public List<T> getContent() {
                return list;
            }

            @Override
            public boolean hasContent() {
                return false;
            }

            @Override
            public Sort getSort() {
                return null;
            }

            @Override
            public boolean isFirst() {
                return this.getNumber()==0;
            }

            @Override
            public boolean isLast() {
                return this.getTotalPages()==(this.getNumber()+1);
            }

            @Override
            public boolean hasNext() {
                return false;
            }

            @Override
            public boolean hasPrevious() {
                return false;
            }

            @Override
            public Pageable nextPageable() {
                return null;
            }

            @Override
            public Pageable previousPageable() {
                return null;
            }

            @Override
            public <S> Page<S> map(Converter<? super T, ? extends S> converter) {
                return null;
            }
        };
        return result;
    }

}

获取mapper的写法

public static RowMapper<TStation> getMapper(){
        RowMapper<TStation> mapper=new RowMapper<TStation>() {
            @Override
            public TStation mapRow(ResultSet rs, int i) throws SQLException {
                TStation s = new TStation();
                s.setId(rs.getInt("id"));
                s.setName(rs.getString("name"));
                return s;
            }
            public boolean isExistColumn(ResultSet rs, String columnName) {
                try {
                    if (rs.findColumn(columnName) > 0 ) {
                        return true;
                    }
                }
                catch (SQLException e) {
                    return false;
                }
                return false;
            }
        };
        return mapper;
    }

使用

JPAPageUtils<TStation> station=new JPAPageUtils<TStation>();
...
station.getPage(getMapper(),jdbcTemplate,sb.toString(),number,size);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JPA中,我们可以使用Criteria API来实现复杂/多条件组合的分页查询。 首先,我们需要创建一个CriteriaBuilder对象,它可以帮助我们构建查询条件和排序规则。然后,我们可以通过调用CriteriaBuilder的createQuery方法来创建查询对象,并指定查询的返回结果类型。接下来,我们需要创建一个Root对象,它表示我们要查询的实体类,并以此为基础构建查询的条件和排序规则。 对于多条件组合查询,我们可以使用Predicate对象来表示不同的查询条件,然后使用CriteriaQuery对象的where方法来添加这些条件。例如,假设我们要查询年龄大于20且性别为女性的用户,我们可以使用如下代码来添加条件: ```java CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<User> query = criteriaBuilder.createQuery(User.class); Root<User> userRoot = query.from(User.class); Predicate agePredicate = criteriaBuilder.greaterThan(userRoot.get("age"), 20); Predicate genderPredicate = criteriaBuilder.equal(userRoot.get("gender"), "女性"); query.where(criteriaBuilder.and(agePredicate, genderPredicate)); ``` 如果我们还需要对查询结果进行分页,我们可以使用CriteriaQuery对象的setFirstResult和setMaxResults方法来设置查询的起始位置和返回的最大记录数。例如,如果我们要查询第一页的10条记录,我们可以使用如下代码: ```java int pageNumber = 1; int pageSize = 10; query.setFirstResult((pageNumber - 1) * pageSize); query.setMaxResults(pageSize); ``` 最后,我们可以通过调用EntityManager的createQuery方法来执行查询,并获取结果集。例如,我们可以使用以下代码来执行查询: ```java TypedQuery<User> typedQuery = entityManager.createQuery(query); List<User> userList = typedQuery.getResultList(); ``` 以上就是使用JPA实现复杂/多条件组合分页查询的基本步骤。通过使用Criteria API,我们可以灵活地构建查询条件和排序规则,实现个性化的查询需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值