SpringDataJpa之强大的手动分页查询(封装与技巧)

背景

JPA对于简单类的查询还是不错的,但通常业务场景不会那么简单,必须用到sql语句来组成一些查询,这个时候我们最好就用手动分页了。类似于MyBatis的用法。

实体类

这是一个员工的实体,即将对他进行操刀

@Entity
@NamedQuery(name="Employee.findAll", query="SELECT e FROM Employee e")
public class Employee implements Serializable {
	private static final long serialVersionUID = 1L;
	@Id
	private int id;
	private Timestamp createtime;
	private String empImage;
	private String empName;
	private String empNum;
	private Timestamp lastupdatetime;
	private String status;
	......
}

Repository类

手写语句,这样的好处在于,全部自定义,功能强大,能想出什么强大的sql就能用到什么强大的功能。

(c.emp_num=?1 or ?1 is null)
这种是做个非空判断,如果是空,就跳过这个条件,不执行。

@Repository
public interface EmployeeRepositrory extends JpaRepository<Employee, Integer> {
	@Query(value ="select * from employee c "
			+ "where (c.emp_num=?1 or ?1 is null) and (c.status=?2 or ?2 is null) "
			+ "order by c.lastupdatetime desc  limit ?3,?4 ",nativeQuery = true)
	List<Employee> findAllList(String empNum,String status,Integer pageNumber,Integer pageSize);
	
	@Query(value ="select count(*) from employee c "
			+ "where (c.emp_num=?1 or ?1 is null) and (c.status=?2 or ?2 is null) "
			+ "order by c.lastupdatetime desc ",nativeQuery = true)
	Integer countAllList(String empNum,String status);
}

Controller控制器

	@PostMapping("/list")
	public ApiReturnObject findAll(String empNum,String status, Integer pageNumber, Integer pageSize) {
			//检查pageNumber, pageSize非空
			CheckUtils.checkPageNumberPageSize(pageNumber, pageSize);
			//获取数据
			List<Employee> list=employeeRepositrory.findAllList(empNum, status,(pageNumber-1)*pageSize, pageSize);
			//获取计数
		    Integer countNum=employeeRepositrory.countAllList(empNum, status);
		    //封装返回
			return ApiReturnUtil.pageManual(pageNumber, pageSize, countNum, list);		
	}

(pageNumber-1)*pageSize, pageSize
这个是因为,mysql的limit x,y;x代表从第几条数据开始,y代表获取多少
所以从数学的角度来讲,这里是(pageNumber-1)*pageSize代表第几条数据开始。
例如一共12条纪录,pageNumber=2,pageSize=10
(pageNumber-1)*pageSize, pageSize=10,10
代表从第10条开始,连续拿10条(09,1019)

如果不会Limit的,这里补充一下,Limit是mysql的语法select * from table limit m,n 其中m是指记录开始的index,从0开始,表示第一条是指从第m+1条开始, 取n条。

ApiReturnUtil&ApiReturnObject

这些根据大家的需要封装,这里这是做个示例

public class ApiReturnObject implements Serializable{
	String errorCode="00";
	Object errorMessage;
	Object returnObject;
	String pageNumber;
	String pageSize;
	String totalElements;
	String totalPages;
	public ApiReturnObject(String pageNumber,String pageSize,String totalElements,String totalPages,String errorCode, Object errorMessage, Object returnObject) {
		super();
		this.pageNumber = pageNumber;
		this.errorCode = errorCode;
		this.errorMessage = errorMessage;
		this.returnObject = returnObject;
		this.pageSize = pageSize;
		this.totalElements = totalElements;
		this.totalPages = totalPages;
	}
}
	public static ApiReturnObject pageManual(Integer pageNumber, Integer pageSize,Integer countNum, List returnObject) {
		return new ApiReturnObject(pageNumber+"",pageSize+"",countNum+"",getTotalPages(countNum, pageSize),"00","success",returnObject);
	}
	
	public static String getTotalPages(Integer countNum, Integer pageSize) {
		if((countNum%pageSize)==0) {
			return ((countNum/pageSize))+"";
		}else {
			return ((countNum/pageSize)+1)+"";
		}
	}

返回格式如下

{
    "errorCode": "00", //返回码,一般00代表成功
    "errorMessage": "success", //返回信息
    "pageNumber": "1", //分页页码
    "pageSize": "10", //分页大小
    "returnObject": [{......}], //返回的list,这里不陈列
    "totalElements": "12",//count语句查询出来有多少条纪录
    "totalPages": "2" //一共分多少页,通过总数/分页大小再+1可以算出((countNum/pageSize)+1)
}

总结

到这里就完成啦,怎么样,是不是很好用,定制性很强。这里有几点技巧提示一下:

  1. 例如你要多关联一些表,那就尽情的再sql语句里面left join吧,如果要先!
  2. 如果有字段是主表没有的,希望加上去的,就加个@Transient注释,代表不实体化这个字段,但是查询又可以关联出来
  3. 判断多用(c.emp_num=?1 or ?1 is null)这个形式的,可以少走很多弯路(除非有特殊需求)
  4. 模糊查询可以参考 SpringDataJPA之@Query with LIKE(JPA模糊查询) https://zhengkai.blog.csdn.net/article/details/80681502
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值