JPA对于简单类的查询还是不错的,但通常业务场景不会那么简单,必须用到sql语句来组成一些查询,这个时候我们最好就用手动分页了。类似于MyBatis的用法。
这是一个员工的实体,即将对他进行操刀
@Entity @NamedQuery (name= "Employee.findAll" , query= "SELECT e FROM Employee e" ) public class Employee implements Serializable { private static final long serialVersionUID = 1 L; @Id private int id; private Timestamp createtime; private String empImage; private String empName; private String empNum; private Timestamp lastupdatetime; private String status;
......
}
手写语句,这样的好处在于,全部自定义,功能强大,能想出什么强大的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);
}
@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条(0~9,10~19)
如果不会Limit的,这里补充一下,Limit是mysql的语法select * from table limit m,n 其中m是指记录开始的index,从0开始,表示第一条是指从第m+1条开始, 取n条。
这些根据大家的需要封装,这里这是做个示例
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)这个形式的,可以少走很多弯路(除非有特殊需求)
凌云 2018-10-23
凌云 2018-12-26
凌云 2018-10-16
sea4sun 2016-02-26
白诗秀儿 2017-05-07
让你心动 2014-11-04
凌云 2018-10-16
睿 2020-05-22
韵竹 2022-12-15
凌云 2018-12-18