文章目录
1、Repository层继承JpaSpecificationExecutor<T>
如下:
@Repository
public interface UserRepository extends JpaRepository<UserDO,Long>, JpaSpecificationExecutor<UserDO> {
}
UserDO:
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
@Table(name = "table_user")
public class UserDO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "username")
private String username;
@Column(name = "user_phone")
private String userPhone;
}
说明:
JpaSpecificationExecutor 实现了多条件查询,有如下几个已定义的接口:
1、获取单个对象数据
2、根据筛选条件查询所有数据
3、根据筛选条件分页查询所有数据
4、根据筛选条件查询所有数据并根据参数进行排序
5、根据筛选条件查询数据总数
public interface JpaSpecificationExecutor<T> {
Optional<T> findOne(@Nullable Specification<T> var1);
List<T> findAll(@Nullable Specification<T> var1);
Page<T> findAll(@Nullable Specification<T> var1, Pageable var2);
List<T> findAll(@Nullable Specification<T> var1, Sort var2);
long count(@Nullable Specification<T> var1);
}
2、Service层编写方法设置筛选条件Specification
示例:根据用户名和电话号码进行筛选:
可以进行模糊查询和大小写设置
private Specification<UserDO> buildWhereClause(String username,String userPhone){
return (Root<UserDO> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
List<Predicate> predicatesList = new ArrayList<>();
//和 != null有什么区别?和isNotEmpty呢?
if(StringUtils.isNotBlank(username)){
predicatesList.add(cb.like(cb.lower(root.get("username").as(String.class)),"%" + username.toLowerCase() + "%"));
}
if(StringUtils.isNotBlank(userPhone)){
predicatesList.add(cb.like(root.get("userPhone").as(String.class), userPhone + "%"));
}
Predicate[] andPredicate = new Predicate[predicatesList.size()];
return cb.and(predicatesList.toArray(andPredicate));
};
}
CriteriaBuilder除了这里的模糊查询like方法之外,还有如下方法:
equal:相等;gt:filed > value;lt:小于;ge:大于等于;le:小于等于;
notLike;notEqual
3、在Service层调用刚刚编写的方法和Repository层的方法实现查询
①非分页查询
@Override
public List<UserBO> findByConditions(UserBO userBO) {
//调用buildWhereClause获取列表
Specification<UserDO> userDOSpecification = buildWhereClause(userBO.getUsername(),userBO.getUserPhone());
List<UserDO> userDOList = userRepository.findAll(userDOSpecification);
//遍历UserDO转为UserBO再对userBOList进行返回即可,不写了
return null;
}
②分页查询
其实只是多加了一个参数page,然后返回参数不同,涉及到怎么把page里面的UserDO拿出来并转为UserBO的问题。
public xxxRespBO findPageByConditions(UserBO userBO, Pageable page){
Specification<UserDO> userDOSpecification = buildWhereClause(userBO.getUsername(),userBO.getUserPhone());
Page<UserDO> userDOPage = userRepository.findAll(userDOSpecification,page);
//通过.getContent();拿到list
List<UserDO> userDOS = userDOPage.getContent();
return null;
}
拿到List之后就容易了,遍历再进行赋值即可获得userBOList,再通过userDOPage.getTotalElements();
和 userDOPage.getTotalPages();
可以获取到总页数和总记录数;通过pageable.getPageNumber();
和 pageable.getPageSize();
可以获取前端传的页码和每页记录数。
把userBOList和这些七七八八的数据一起放到userRespBO中封装起来传到上一层,再把userBOList转成需要的格式的List,再封装起来(RespDTO)传给前端。
上层调用示例:示例中的1和10由前端传入
xxxRespBO xxx = findPageByConditions(userBO, new PageRequest(1, 10));
当然其实也可以直接findPageByConditions(xxreqBO)
,(也即页码和页数直接封装在xxreqBO中)这样的话findPageByConditions方法中少了一个pageable参数,可以在该方法中通过如下方法获得:
Pageable pageable = PageRequest.of(从xxreqBO中获取到的页码参数, 每页记录参数);