前言
自己写的一个后台管理系统,在多条件查询客户信息时需要进行分页处理,如果用MyBatis的话,PageHelper插件就挺好用的,但是既然用了QueryDSL来进行查询操作的话,就用它的方法进行分页。
查询实体类创建
先创建一个客户实体类Client,对应数据库里的client表,里面是客户信息的属性
@Data
@Entity
@Table(name="client")
public class Client implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "clientId")
private int clientId;
@Column(name = "clientName")
private String clientName;
@Column(name = "address")
private String address;
@Column(name = "cardId")
private String cardId;
@Column(name = "birthday")
private String birthday;
@Column(name = "createDate")
private String createDate;
@Column(name = "clientType")
private String clientType;
@Column(name = "phone")
private String phone;
@Column(name = "eMail")
private String eMail;
@Column(name="clientNo")
private String clientNo;
@Column(name="status")
private int status;
}
查询实体类设计
既然包含条件查询,需要把查询条件封装成一个新的类,在controller层接收,然后传给Service层进行处理,具体如下:
@Data
public class ClientReq {
private String clientNo; //客户号
private String clientName; //客户名
private String cardId; //证件号
private String startDate; //起始日期(范围查询生日)
private String endDate;//截止日期(范围查询生日)
private String clientType;//客户类型
private String phone;
private long pageNum=1;//当前页数(默认为1)
private long pageSize=5;//每页数量(默认为5)
}
多条件分页查询的实现
多条件分页查询在Service层实现,因为使用QueryDSL实现,需要两个类:EntityManager和JPAQueryFactory,并且JPAQueryFactory在需要使用@PostConstructz注解标记,进行初始化,代码如下
private JPAQueryFactory jpaQueryFactory;
@Autowired
private EntityManager entityManager;
@PostConstruct
public void initFactory(){
jpaQueryFactory = new JPAQueryFactory(entityManager);
}
之后就是实现分页条件查询的方法,因为涉及多条件判断,前端传来的筛选条件可能有空的字段,所以需要使用BooleanBuilder类进行动态的条件筛选,这里单独封装一个方法,用来判断筛选条件哪些为空,并且将不为空的判断条件加入到sql中,具体实现如下:
public void checkCondition(BooleanBuilder booleanBuilder,QClient qClient,ClientReq clientReq){
if(!StringUtils.isEmpty(clientReq.getClientName()))
booleanBuilder.and(qClient.clientName.contains(clientReq.getClientName()));
if(!StringUtils.isEmpty(clientReq.getClientNo()))
booleanBuilder.and(qClient.clientNo.contains(clientReq.getClientNo()));
if(!StringUtils.isEmpty(clientReq.getCardId()))
booleanBuilder.and(qClient.cardId.contains(clientReq.getCardId()));
if(!StringUtils.isEmpty(clientReq.getClientType()))
booleanBuilder.and(qClient.clientType.contains(clientReq.getClientType()));
if(!StringUtils.isEmpty(clientReq.getPhone()))
booleanBuilder.and(qClient.phone.contains(clientReq.getPhone()));
if(clientReq.getStartDate()!=null&&clientReq.getEndDate()!=null)
booleanBuilder.and(qClient.birthday.between(clientReq.getStartDate(),clientReq.getEndDate()));
}
最后就是核心代码,分页查询的实现了,很简单,几行就结束了
public Map<String,Object> queryClientByRequire(ClientReq clientReq) {
QClient qClient = QClient.client;
HashMap<String, Object> result = new HashMap<>();
BooleanBuilder booleanBuilder = new BooleanBuilder();
checkCondition(booleanBuilder,qClient,clientReq);
long count = jpaQueryFactory.select(qClient.count()).from(qClient).
where(booleanBuilder).fetchOne();
List<Client> clientList = jpaQueryFactory.select(qClient).
from(qClient).
where(booleanBuilder).
orderBy(qClient.clientId.asc()).
offset((clientReq.getPageNum()-1)*clientReq.getPageSize()).
limit(clientReq.getPageSize()).
fetch();
result.put("clientList",clientList);
result.put("sum",count);
return result;
}
QueryDSL的语法还是很好理解的,就像是把方法拼装成SQL语句,其中offset()表示从第几页开始查,limit()表示查询条数,最后fetch()方法会返回对应泛型的List,即查询的数据,而另一个count记录了查询的条数,用来返回给前端做处理。