侧边栏壁纸
博主头像
术业有道之编程博主等级

亦是三月纷飞雨,亦是人间惊鸿客。亦是秋霜去叶多,亦是风华正当时。

  • 累计撰写 99 篇文章
  • 累计创建 50 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

一个很实用的querydsl的工具包

Administrator
2020-09-01 / 0 评论 / 0 点赞 / 80 阅读 / 26777 字

最近 querydsl 用的比较多,在多表查询分页的情况下返回的数据对象不能非常便捷的拿来直接操作,之前的写法可能是类似这样(担心吐的可以直接跳过):

JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
        QueryResults<Tuple> results = queryFactory.select(qTrade.tradeNo, qTradeDetails.description, qTradeDetails.itemImageUrl,
                qTradeDetails.itemTitle, qTradeDetails.lessonName, qTradeDetails.ageName, qTradeDetails.groupName, qTrade.totalAmount,
                qPay.payAmount, qPay.discountsPayAmount, qTradeDetails.nick, qTrade.status, qPay.status, qTrade.createdAt, qPay.payTime,
                qTradeDetails.sponsor, qGroup.groupId, qGroup.status, qPay.payChannel, qPay.couponName, qGroup.teachLocationAlias,
                qGroup.title, qGroup.memberMinCount, qGroup.teachLocation, qGroup.teachLocationAlias, qGroup.memberMinCount,
                qGroup.groupName, qGroup.memberMaxCount)
                .from(qTrade)
                .leftJoin(qTradeDetails).on(qTrade.tradeNo.eq(qTradeDetails.tradeNo))
                .leftJoin(qPay).on(qTrade.tradeNo.eq(qPay.tradeNo))
                .leftJoin(qGroup).on(qTradeDetails.groupNo.eq(qGroup.groupId))
                .where(ExpressionUtils.allOf(wherePredicateList))
                .orderBy(qTrade.createdAt.desc())
                .offset((pageRequest.getPageIndex() - 1) * pageRequest.getPageSize())
                .limit(pageRequest.getPageSize())
                .fetchResults();
        List<TradeListVO> list = new ArrayList<>();
        results.getResults().forEach(row -> {
            list.add(pageShow(TradeListVO.builder()
                    .tradeNo(row.get(qTrade.tradeNo))
                    .description(row.get(qTradeDetails.description))
                    .itemImageUrl(getOneImage(row.get(qTradeDetails.itemImageUrl)))
                    .itemTitle(row.get(qTradeDetails.itemTitle))
                    .lessonName(row.get(qTradeDetails.lessonName))
                    .ageName(row.get(qTradeDetails.ageName))
                    .groupName(row.get(qTradeDetails.groupName))
                    .tradeGroupName(row.get(qGroup.groupName))
                    .totalAmount(row.get(qTrade.totalAmount))
                    .payAmount(row.get(qPay.payAmount))
                    .discountsPayAmount(row.get(qPay.discountsPayAmount))
                    .nick(row.get(qTradeDetails.nick))
                    .status(row.get(qTrade.status))
                    .payStatus(row.get(qPay.status))
                    .createdAt(row.get(qTrade.createdAt))
                    .payTime(row.get(qPay.payTime))
                    .sponsor(row.get(qTradeDetails.sponsor))
                    .groupNo(row.get(qGroup.groupId))
                    .groupStatus(row.get(qGroup.status))
                    .payChannel(row.get(qPay.payChannel))
                    .couponName(row.get(qPay.couponName))
                    .shareDetail(getShareDetail(row.get(qTradeDetails.nick), row.get(qGroup.teachLocationAlias), row.get(qGroup.title)))
                    .userPhotos(getUserPhotos(row.get(qGroup.groupId)))
                    .teachLocation(row.get(qGroup.teachLocation))
                    .teachLocationAlias(row.get(qGroup.teachLocationAlias))
                    .groupMinCount(row.get(qGroup.memberMinCount))
                    .groupMaxCount(row.get(qGroup.memberMaxCount))
                    .build()));
        });

问题:

  • 想要把查询的结果组装到 List<TradeListVO> list = new ArrayList<>(); 这块代码写的直接吐了。还不如直接 sql 语句,TradeListVO 需要实现一下 org.springframework.jdbc.core.RowMappermapRow 方法,通过反射完成赋值。
  • javax.persistence.EntityManager 基于 jpa 的实现直接被注入,容易引发不安全。

一、工具包

QuerydslUtlis

  • java
@Slf4j
@Scope
@Component
public class QuerydslUtlis {
    @Autowired
    EntityManager entityManager;
    JPAQueryFactory queryFactory;
    ObjectMapper objectMapper;

    @PostConstruct
    void initFactory() {
        log.info("开始实例化JPAQueryFactory");
        queryFactory = new JPAQueryFactory(entityManager);
    }

    @PostConstruct
    void objectMapperConfig() {
        if (objectMapper == null) objectMapper = new ObjectMapper();
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 获得查询工厂实例
     *
     * @return JPAQueryFactory
     */
    public JPAQueryFactory getQueryFactory() {
        if (queryFactory == null) initFactory();
        return queryFactory;
    }

    /**
     * 将com.querydsl.core.Tuple转换为需要的bean
     *
     * @param tuple 查询得到的数据
     * @param exprs 查询的列
     * @param clazz 要转换的目标 class类型
     * @return 返回根据 clazz转换的 class -> Object对象
     * ==== 注意 =======
     * @see QuerydslUtlis#objectMapperConfig
     * 需要在有 objectMapperConfig 的配置前提
     * @see com.fasterxml.jackson.annotation.JsonProperty
     * 默认取最后的字段名字与clazz的类字段名称匹配,如有不匹配的字段 请自行使用@JsonProperty注解来匹配
     * 匹配规则为 exprs 查询参数的全称
     * <p>
     * 示例:
     * querydslUtlis.getBean(it, exprs, QueryDeviceFlowRulesVO::class.java) as QueryDeviceFlowRulesVO
     */
    public <T> Object getBean(Tuple tuple, Expression<?>[] exprs, Class<T> clazz) {
        Map<String, Object> map = getBeanMap(tuple, exprs);
        if (map.isEmpty()) return new Object();
        return mapToBean(map, clazz);
    }


    /**
     * 将List<com.querydsl.core.Tuple>转换为需要的List<bean>
     *
     * @param tuples 查询得到的数据结果集
     * @param exprs  查询的列
     * @param clazz  要转换的目标 class类型
     * @return 返回根据 clazz转换的 class -> List<Object>对象
     * ==== 注意 =======
     * @see QuerydslUtlis#objectMapperConfig
     * 需要在有 objectMapperConfig 的配置前提
     * @see com.fasterxml.jackson.annotation.JsonProperty
     * 默认取最后的字段名字与clazz的类字段名称匹配,如有不匹配的字段 请自行使用@JsonProperty注解来匹配
     * 匹配规则为 exprs 查询参数的全称
     * 示例:
     * querydslUtlis.getCollection(results.results, exprs, QueryDeviceVO::class.java) as List<QueryDeviceVO>
     */
    public <T> List<T> getCollection(List<Tuple> tuples, Expression<?>[] exprs, Class<T> clazz) {
        List<Map<String, Object>> list = new ArrayList<>();
        tuples.forEach(tuple -> {
            Map<String, Object> map = getBeanMap(tuple, exprs);
            if (!map.isEmpty()) list.add(map);
        });
        return listToListBean(list, getCollectionType(List.class, clazz));
    }

    /**
     * 将内容转换为mapbean
     *
     * @param tuple 查询得到的数据
     * @param exprs 查询的列
     * @return 返回一个基于bean属性的 map
     */
    Map<String, Object> getBeanMap(Tuple tuple, Expression<?>[] exprs) {
        Map<String, Object> map = new HashMap<>();
        Arrays.asList(exprs).forEach(expression -> {
            Object value = tuple.get(expression);
            String key = expression.toString();
            int index = key.lastIndexOf(".");
            String subKey = "";
            if (index != -1) subKey = key.substring(key.lastIndexOf(".") + 1);
            if (!subKey.isEmpty() && !map.containsKey(subKey)) {
                map.put(subKey, value);
            } else {
                map.put(key, value);
            }
        });
        return map;
    }

    // 将对象转成字符串
    String objectToString(Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("json转换失败", e);
        }
        return null;
    }

    // 将Map转成指定的Bean
    <T> Object mapToBean(Map<?, ?> map, Class<T> clazz) {
        try {
            return objectMapper.readValue(objectToString(map), clazz);
        } catch (IOException e) {
            log.error("json转换失败", e);
        }
        return null;
    }

    // 将Bean转成Map
    Map<?, ?> beanToMap(Object obj) {
        try {
            return objectMapper.readValue(objectToString(obj), Map.class);
        } catch (Exception e) {
            log.error("json转换失败", e);
        }
        return null;
    }

    // 将list<map>转成指定的list<Bean>
    <T, R> List<R> listToListBean(Collection<T> list, JavaType clazz) {
        try {
            return objectMapper.readValue(objectToString(list), clazz);
        } catch (Exception e) {
            log.error("json转换失败", e);
        }
        return null;
    }

    /**
     * 获取泛型的Collection Type
     *
     * @param collectionClass 泛型的Collection
     * @param elementClasses  元素类
     * @return JavaType Java类型
     * @since 1.0
     */
    JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }
}
  • kotlin
@Scope
@Component
class QuerydslUtlis @Autowired
constructor(private val entityManager: EntityManager) {
    private val logger = LoggerFactory.getLogger(javaClass)
    //查询工厂实体
    private var queryFactory: JPAQueryFactory? = null
    //jackson对象
    private var objectMapper: ObjectMapper? = null

    @PostConstruct
    private fun initFactory() {
        logger.info("开始实例化JPAQueryFactory")
        queryFactory = JPAQueryFactory(entityManager)
    }

    @PostConstruct
    private fun objectMapperConfig() {
        if (objectMapper == null) objectMapper = ObjectMapper()
        objectMapper!!.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
        objectMapper!!.dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    }
    
    /**
     * 获得查询工厂实例
     *
     * @return JPAQueryFactory
     */
    fun getQueryFactory(): JPAQueryFactory {
        if (queryFactory == null) initFactory()
        return queryFactory!!
    }

    /**
     * 将com.querydsl.core.Tuple转换为需要的bean
     *
     * @param tuple 查询得到的数据
     * @param exprs 查询的列
     * @param clazz 要转换的目标 class类型
     * @return 返回根据 clazz转换的 class -> Object对象
     * ==== 注意 =======
     * @see objectMapperConfig
     * 需要在有 objectMapperConfig 的配置前提
     * @see com.fasterxml.jackson.annotation.JsonProperty
     * 默认取最后的字段名字与clazz的类字段名称匹配,如有不匹配的字段 请自行使用@JsonProperty注解来匹配
     * 匹配规则为 exprs 查询参数的全称
     *
     * 示例:
     * querydslUtlis.getBean(it, exprs, QueryDeviceFlowRulesVO::class.java) as QueryDeviceFlowRulesVO
     */
    fun <T> getBean(tuple: Tuple, exprs: Array<Expression<*>>, clazz: Class<T>): Any {
        val map: Map<String, Any> = getBeanMap(tuple, exprs)
        return if (map.isEmpty()) Any() else mapToBean(map, clazz)
    }

    /**
     * 将内容转换为mapbean
     *
     * @param tuple 查询得到的数据
     * @param exprs 查询的列
     * @return 返回一个基于bean属性的 map
     */
    private fun getBeanMap(tuple: Tuple, exprs: Array<Expression<*>>): Map<String, Any> {
        val map: MutableMap<String, Any> = HashMap()
        exprs.forEach {
            var value = tuple[it]
            if (value == null) value = Any()
            val key = it.toString()
            val index = key.lastIndexOf(".")
            var subKey = ""
            if (index != -1) subKey = key.substring(key.lastIndexOf(".") + 1)
            if (subKey.isNotEmpty() && !map.containsKey(subKey)) {
                map[subKey] = value
            } else {
                map[key] = value
            }
        }
        return map
    }

    /**
     * 将List<com.querydsl.core.Tuple>转换为需要的List<bean>
     *
     * @param tuples 查询得到的数据结果集
     * @param exprs 查询的列
     * @param clazz 要转换的目标 class类型
     * @return 返回根据 clazz转换的 class -> List<Object>对象
     * ==== 注意 =======
     * @see objectMapperConfig
     * 需要在有 objectMapperConfig 的配置前提
     * @see com.fasterxml.jackson.annotation.JsonProperty
     * 默认取最后的字段名字与clazz的类字段名称匹配,如有不匹配的字段 请自行使用@JsonProperty注解来匹配
     * 匹配规则为 exprs 查询参数的全称
     * 示例:
     * querydslUtlis.getList(results.results, exprs, QueryDeviceVO::class.java) as List<QueryDeviceVO>
     */
    fun <T> getList(tuples: MutableList<Tuple>, exprs: Array<Expression<*>>, clazz: Class<T>): MutableList<T> {
        val list = mutableListOf<Map<String, Any>>()
        tuples.forEach { tuple ->
            val map = getBeanMap(tuple, exprs)
            if (map.isNotEmpty()) list.add(map)
        }
        return listToListBean(list, getCollectionType(List::class.java, clazz))
    }

    // 将对象转成字符串
    @Throws(Exception::class)
    private fun objectToString(obj: Any): String {
        return objectMapper!!.writeValueAsString(obj)
    }

    // 将Map转成指定的Bean
    @Throws(Exception::class)
    private fun <T> mapToBean(map: Map<*, *>, clazz: Class<T>): Any {
        return objectMapper!!.readValue(objectToString(map), clazz)!!
    }

    // 将Bean转成Map
    @Throws(Exception::class)
    private fun beanToMap(obj: Any): Map<*, *> {
        return objectMapper!!.readValue(objectToString(obj), MutableMap::class.java)
    }

    // 将list<map>转成指定的list<Bean>
    @Throws(Exception::class)
    private fun <T, R> listToListBean(list: MutableList<T>, clazz: JavaType): MutableList<R> {
        return objectMapper!!.readValue(objectToString(list), clazz)
    }

    /**
     * 获取泛型的Collection Type
     *
     * @param collectionClass 泛型的Collection
     * @param elementClasses  元素类
     * @return JavaType Java类型
     * @since 1.0
     */
    private fun getCollectionType(collectionClass: Class<*>, vararg elementClasses: Class<*>): JavaType {
        return objectMapper!!.typeFactory.constructParametricType(collectionClass, *elementClasses)
    }
}

会自动创建好一个可用的查询工厂对象,并且提供基于 jackson 的数据序列化方式,主动用到的功能只需要关注 public 修饰的方法即可

二、使用工具包

QuerydslUtlis

  • java
QIssueRecord qIssueRecord = QIssueRecord.issueRecord;
        QFAQsDict qFAQsDict = QFAQsDict.fAQsDict;
        QSimilarityQuestionRecord qSimilarityQuestionRecord = QSimilarityQuestionRecord.similarityQuestionRecord;
        Expression<?>[] arrayExpressions = {
                qIssueRecord.issueNo,
                qIssueRecord.createdAt, qIssueRecord.type, qIssueRecord.issueText, qIssueRecord.issueSpeech,
                qIssueRecord.discernIssueSpeechText, qFAQsDict.answerText, qFAQsDict.answerSpeech, qSimilarityQuestionRecord.questionReplies
                , qSimilarityQuestionRecord.compoundQuestionSpeech
        };
        QueryResults<Tuple> results = querydslUtlisObjectFactory.getObject().getQueryFactory().select(arrayExpressions)
                .from(qIssueRecord)
                .leftJoin(qSimilarityQuestionRecord).on(qSimilarityQuestionRecord.issueNo.eq(qIssueRecord.issueNo))
                .leftJoin(qFAQsDict).on(qFAQsDict.no.eq(qIssueRecord.answerNo))
                .orderBy(qIssueRecord.createdAt.desc())
                .offset((pageRequest.getPageIndex() - 1) * pageRequest.getPageSize())
                .limit(pageRequest.getPageSize())
                .fetchResults();
        List<AnswerVO> list = querydslUtlisObjectFactory.getObject().getCollection(results.getResults(),
                arrayExpressions, AnswerVO.class);
  • kotlin
 val qDeviceRules = QDeviceRules.deviceRules
        val qFlowRules = QFlowRules.flowRules
        var rredicate: Predicate? = null
        if (StringUtils.isNotBlank(aPageRequest.query)) rredicate = qDeviceRules.deviceNo.eq(aPageRequest.query)
        val exprs = arrayOf<Expression<*>>(qDeviceRules.deviceNo, qDeviceRules.deleted, qFlowRules.rulesNo, qFlowRules.flowMax,
                qFlowRules.startTime, qFlowRules.endTime)
        val results = querydslUtlisObjectFactory.`object`.getQueryFactory()
                .select(*exprs)
                .from(qDeviceRules)
                .where(ExpressionUtils.allOf(rredicate))
                .leftJoin(qFlowRules)
                .on(qDeviceRules.rulesNo.eq(qFlowRules.rulesNo))
                .orderBy(qDeviceRules.createAt.desc())
                .offset((aPageRequest.pageIndex!! - 1) * aPageRequest.pageSize!!)
                .limit(aPageRequest.pageSize!!)
                .fetchResults()
        return PageUtlis.retPage(results, querydslUtlisObjectFactory.`object`.getList(results.results, exprs,
                QueryDeviceFlowRulesVO::class.java))

这里当调用了 querydslUtlisgetList 后就会将查询的结果转换成对应的输出List<VO> 类,其中出现字段解析,以及字段重复的问题请参考 getList 方法的说明,这里的解决方案是 jackson 的通用方案。

这里使用 getList 返回 list 是因为可能转换得到的结果需要再次排序等操作。

我使用了 spring 单例的方式操作 querydslUtlis

以下是一个输出 VO 类定义的例子(注意看注释):

   //当数据实体定义的字段属性名称与当前VO类的字段名一致时,会直接对应转换
   @ApiModelProperty(value = "问题编号", dataType = "string")
    String issueNo;

/**
 * 当数据实体定义的字段属性名称与当前VO类的字段名不一致时,使用
 * @JsonProperty 进行定义转换的字段
 */
    @JsonProperty("createdAt")
    @ApiModelProperty(value = "提问时间", dataType = "string")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    Date issueCreatedAt;

三、基于当前工具包的分页工具封装

PageUtlis

这个工具包可以辅助上面介绍的工具包将得到的结果直接传入下面的工具包方法达到一行代码完成 querydsl 数据解析加视图 VO 数据组装返回的过程

因为封装分页对象的返回对象结构可能不同,以下代码仅供参考:

  • java
/**
     * 分页 返回 PageResult
     * val results = querydslUtlis.getQueryFactory()
     * .select(*exprs)
     * .from(qDevice)
     * .where(ExpressionUtils.allOf(rredicate))
     * .orderBy(qDevice.createAt.desc())
     * .offset((aPageRequest.pageIndex!! - 1) * aPageRequest.pageSize!!)
     * .limit(aPageRequest.pageSize!!)
     * .fetchResults()
     * return PageUtlis.retPage(results, querydslUtlis.getCollection(results.results, exprs, QueryDeviceVO::class.java) as Collection<QueryDeviceVO>)
     */
    public static <T, R> PageResult<R> retPage(QueryResults<T> queryResults, Collection<R> list) {
        PageResult<R> page = new PageResult<R>();
        page.setResult(list);
        PageResult.PageInfo info = new PageResult.PageInfo();
        info.setPageIndex((int) queryResults.getOffset());
        info.setPageSize((int) queryResults.getLimit());
        info.setPageTotal(queryResults.getResults().size());
        info.setTotal(queryResults.getTotal());
        info.setLastPage(info.getPageIndex() * info.getPageSize() - info.getTotal() >= 0);
        page.setPageInfo(info);
        return page;
    }

    /**
     * 分页 返回 PageResult
     * 例如
     * val results = querydslUtlis.getQueryFactory()
     * .select(*exprs)
     * .from(qDeviceRules)
     * .where(ExpressionUtils.allOf(rredicate))
     * .leftJoin(qFlowRules)
     * .on(qDeviceRules.rulesNo.eq(qFlowRules.rulesNo))
     * .orderBy(qDeviceRules.createAt.desc())
     * .offset((aPageRequest.pageIndex!! - 1) * aPageRequest.pageSize!!)
     * .limit(aPageRequest.pageSize!!)
     * .fetchResults()
     * <p>
     * return PageUtlis.retPage(results,Function<Tuple, QueryDeviceFlowRulesVO> {
     * querydslUtlis.getBean(it, exprs, QueryDeviceFlowRulesVO::class.java) as QueryDeviceFlowRulesVO
     * })
     */
    public static <T, R> PageResult<R> retPage(QueryResults<T> queryResults, Function<T, R> function) {
        PageResult<R> page = new PageResult<R>();
        page.setResult(toList(queryResults.getResults(), function));
        PageResult.PageInfo info = new PageResult.PageInfo();
        info.setPageIndex((int) queryResults.getOffset());
        info.setPageSize((int) queryResults.getLimit());
        info.setPageTotal(queryResults.getResults().size());
        info.setTotal(queryResults.getTotal());
        info.setLastPage(info.getPageIndex() * info.getPageSize() - info.getTotal() >= 0);
        page.setPageInfo(info);
        return page;
    }
    public static <T, E> List<E> toList(Collection<T> col, Function<T, E> function) {
        return col.stream().map(function).collect(Collectors.toList());
    }
  • kotlin
/**
     * 分页 返回 PageResult
     * val results = querydslUtlis.getQueryFactory()
     * .select(*exprs)
     * .from(qDevice)
     * .where(ExpressionUtils.allOf(rredicate))
     * .orderBy(qDevice.createAt.desc())
     * .offset((aPageRequest.pageIndex!! - 1) * aPageRequest.pageSize!!)
     * .limit(aPageRequest.pageSize!!)
     * .fetchResults()
     *  return PageUtlis.retPage(results, querydslUtlis.getCollection(results.results, exprs, QueryDeviceVO::class.java) as Collection<QueryDeviceVO>)
     */
    fun <T, R> retPage(queryResults: QueryResults<T>, list: Collection<R>): PageResult<R> {
        val page = PageResult<R>()
        page.result = list
        val pageInfo = PageResult.PageInfo()
        pageInfo.pageIndex = queryResults.offset
        pageInfo.pageSize = queryResults.limit
        pageInfo.total = queryResults.total
        pageInfo.pageTotal = queryResults.results.size.toLong()
        pageInfo.isLastPage = pageInfo.pageIndex!! * pageInfo.pageSize!! - pageInfo.total!! >= 0
        page.pageInfo = pageInfo
        return page
    }

    /**
     * 分页 返回 PageResult
     * 例如
     * querydslUtlis.getQueryFactory()
     *  .select(*exprs)
     *  .from(qDeviceRules)
     *  .where(ExpressionUtils.allOf(rredicate))
     *  .leftJoin(qFlowRules)
     *  .on(qDeviceRules.rulesNo.eq(qFlowRules.rulesNo))
     *  .orderBy(qDeviceRules.createAt.desc())
     *  .offset((aPageRequest.pageIndex!! - 1) * aPageRequest.pageSize!!)
     *  .limit(aPageRequest.pageSize!!)
     *  .fetchResults(), Function<Tuple, QueryDeviceFlowRulesVO> {
     *    querydslUtlis.getBean(it, exprs, QueryDeviceFlowRulesVO::class.java) as QueryDeviceFlowRulesVO
     * }
     */
    fun <T, R> retPage(queryResults: QueryResults<T>, function: Function<T, R>): PageResult<R> {
        val page = PageResult<R>()
        page.result = toList(queryResults.results, function)
        val pageInfo = PageResult.PageInfo()
        pageInfo.pageIndex = queryResults.offset
        pageInfo.pageSize = queryResults.limit
        pageInfo.total = queryResults.total
        pageInfo.pageTotal = queryResults.results.size.toLong()
        pageInfo.isLastPage = pageInfo.pageIndex!! * pageInfo.pageSize!! - pageInfo.total!! >= 0
        page.pageInfo = pageInfo
        return page
    }

    private fun <T, R> toList(col: Collection<T>, function: Function<T, R>): List<R>? {
        return col.stream().map(function).collect(Collectors.toList<R>())
    }

整合两个工具包之后业务层完整的操作基本上是这样的:
  • java
public PageResult<AnswerVO> page(PageRequest pageRequest, String userNo) {
        QIssueRecord qIssueRecord = QIssueRecord.issueRecord;
        QFAQsDict qFAQsDict = QFAQsDict.fAQsDict;
        QSimilarityQuestionRecord qSimilarityQuestionRecord = QSimilarityQuestionRecord.similarityQuestionRecord;
        Expression<?>[] arrayExpressions = {
                qIssueRecord.issueNo,
                qIssueRecord.createdAt, qIssueRecord.type, qIssueRecord.issueText, qIssueRecord.issueSpeech,
                qIssueRecord.discernIssueSpeechText, qFAQsDict.answerText, qFAQsDict.answerSpeech, qSimilarityQuestionRecord.questionReplies
                , qSimilarityQuestionRecord.compoundQuestionSpeech
        };
        QueryResults<Tuple> results = querydslUtlisObjectFactory.getObject().getQueryFactory().select(arrayExpressions)
                .from(qIssueRecord)
                .leftJoin(qSimilarityQuestionRecord).on(qSimilarityQuestionRecord.issueNo.eq(qIssueRecord.issueNo))
                .leftJoin(qFAQsDict).on(qFAQsDict.no.eq(qIssueRecord.answerNo))
                .orderBy(qIssueRecord.createdAt.desc())
                .offset((pageRequest.getPageIndex() - 1) * pageRequest.getPageSize())
                .limit(pageRequest.getPageSize())
                .fetchResults();
        return PageUtils.retPage(results, querydslUtlisObjectFactory.getObject().getCollection(results.getResults(),
                arrayExpressions, AnswerVO.class));
   }
  • kotlin
fun queryDeviceFlowRules(aPageRequest: APageRequest): PageResult<QueryDeviceFlowRulesVO> {
        val qDeviceRules = QDeviceRules.deviceRules
        val qFlowRules = QFlowRules.flowRules
        var rredicate: Predicate? = null
        if (StringUtils.isNotBlank(aPageRequest.query)) rredicate = qDeviceRules.deviceNo.eq(aPageRequest.query)
        val exprs = arrayOf<Expression<*>>(qDeviceRules.deviceNo, qDeviceRules.deleted, qFlowRules.rulesNo, qFlowRules.flowMax,
                qFlowRules.startTime, qFlowRules.endTime)
        val results = querydslUtlisObjectFactory.`object`.getQueryFactory()
                .select(*exprs)
                .from(qDeviceRules)
                .where(ExpressionUtils.allOf(rredicate))
                .leftJoin(qFlowRules)
                .on(qDeviceRules.rulesNo.eq(qFlowRules.rulesNo))
                .orderBy(qDeviceRules.createAt.desc())
                .offset((aPageRequest.pageIndex!! - 1) * aPageRequest.pageSize!!)
                .limit(aPageRequest.pageSize!!)
                .fetchResults()
        return PageUtlis.retPage(results, querydslUtlisObjectFactory.`object`.getList(results.results, exprs,
                QueryDeviceFlowRulesVO::class.java))
   }

个人公众号

0

评论区