Querydsl-JPA学习(踩坑篇)

5,585 阅读2分钟

1.简介:

本篇文章记录在使用Querydsl-JPA过程中遇到一些问题,坑,大家在以后使用过程中再遇到这些问题时可少浪费一些时间.

2.问题:

2.1:分页问题:spring-data-jpa与query-dsl-jpa的分页区别:

2.1.1: 在使用spring-data-jpa处理分页时我们可以这么写:通过spring-data提供的PageRequest分页类处理,此处我们无需进行计算,提供查询页码以及分页的数量即可完成。

public void getUserListByPageSpringData() {
    int pageNum = 1;
    int pageSize = 2;
    User user = new User();
    user.setAge(10);
    Example<User> of = Example.of(user);
    Page<User> all = userDao.findAll(of, PageRequest.of(pageNum - 1, pageSize));
    List<User> content = all.getContent();
    long totalElements = all.getTotalElements();
    String contentStr = JSON.toJSONString(content);
    System.out.println("spring-data-jpa 分页查询年龄为10的结果:"+contentStr);
}

查看源码PageRequest继承的抽象类AbstractPageRequest为我们进行了计算:

2.1.2: 在使用query-dsl-jpa处理分页时,jpaQueryFactory分别提供了offset和 limit方法:此处需要我们进行计算处理。

public void getUserListByPage() {
    int pageNo = 1;
    int pageSize = 10;
    int pageNumber = (pageNo-1)*pageSize;
    QUser user = QUser.user;
    QueryResults<User> userQueryResults =
            jpaQueryFactory.selectFrom(user).offset(pageNumber).limit(pageSize).fetchResults();
    String userQueryResultsStr = JSON.toJSONString(userQueryResults);
    System.out.println("单表分页的结果集:"+userQueryResultsStr);
}

2.2. 查询扩展字段时怎么处理(该扩展字段一直属性)?

import com.querydsl.core.types.dsl.Expressions;

String infoId = "filed01";

StringPath field = Expressions.stringPath(qArBillExpense, infoId);
    List<ArBillExpense> expenses = jpaQueryFactory.selectFrom(qArBillExpense).leftJoin(qArBill).on(qArBill.id.eq(qArBillExpense.billId))
            .where(field.eq(identityCode), qArBill.isIncomeHistory.eq(ArConstant.YES), qArBill.billType.eq("EXP_INCOMETAX"), qArBillExpense.expenseType.eq("LABOR_OTHER"))
            .fetch();

2.3. queryDsl 两个表关联,关联的字段类型不一样,编译不通过怎么办?

import com.querydsl.core.types.dsl.Expressions;

Expression sourceCode = qArSysDataSource.sourceCode;
NumberExpression numberExpression = Expressions.asNumber(sourceCode);

jpaQueryFactory.selectFrom(qArBill).leftJoin(qArSysDataSource).on(qArBill.billStatus.eq(numberExpression))

2.4. 对条件里的的字段做字符拼接怎么处理?

如下这张图,用Querydsl-JPA实现下面的条件字段的字符串拼接:(我的场景是判断用户输入的号码是否在数据库存在,用户输入的格式为:No111,No222,数据库存的也是该格式,但是我要检验No111是否存在?)

拼接的时候会出现编译不通过,类型不匹配。

可以折中处理,使用模糊查询的方式:代码如下

import com.querydsl.core.BooleanBuilder;

    QArBill qArBill = QArBill.arBill;
    QArBillExpense qArBillExpense = QArBillExpense.arBillExpense;
    
    BooleanBuilder booleanBuilder = new BooleanBuilder();
    booleanBuilder.and(qArBillExpense.invoiceNo.isNotNull());
    
    BooleanBuilder invoiceNoBuilder = new BooleanBuilder();
    for (String invoiceNo : invoiceNos) {
        invoiceNoBuilder.or(qArBillExpense.invoiceNo.startsWith(invoiceNo.concat(",")));
        invoiceNoBuilder.or(qArBillExpense.invoiceNo.contains((",").concat(invoiceNo).concat(",")));
        invoiceNoBuilder.or(qArBillExpense.invoiceNo.endsWith((",").concat(invoiceNo)));
        invoiceNoBuilder.or(qArBillExpense.invoiceNo.eq(invoiceNo));
    }
    booleanBuilder.and(invoiceNoBuilder);
    
    List<ArBillInvoiceCheckVo> arBillList = jpaQueryFactory.select(Projections.bean(ArBillInvoiceCheckVo.class,
            qArBill.inputor.as("inputor"), qArBill.billNo.as("billNo"), qArBillExpense.invoiceNo.as("invoiceNo"))).from(qArBill).join(qArBillExpense)
            .on(qArBill.id.eq(qArBillExpense.billId))
            .where(booleanBuilder).fetch();

装载后的sql语句如下图: