最近用datatable做了一個后台分頁,但是后台實體原本沒寫DTO。就碰到的問題做了一下總結
一、datatable使用get方式傳數據到后台,這是正常的后台分頁,不涉及過濾查詢和前端傳遞的排序字段,后面會細講
后台使用
@GetMapping("/jobs")
@ResponseBody
public ResponseEntity<List<AuditJob>> getAllTestPages(@ApiParam Pageable pageable) {
log.debug("REST request to get a page of TestPages");
Page<AuditJob> page = auditJobRepository.findAll(pageable);
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/test-pages");
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
}
二、使用DTO
sql語句:
這里需要注意的是,
1、這里用到了DTO,自己建了一個實體類的DTO,只查詢出自己需要的字段,但是字段名必須和Dto的構造參數字段操持一致
2、自定義的查詢方法,要加上@Modifing
3、這里使用的對象查詢,所以sql語句中要和實體的屬性名對應,如果要寫原生sql語句,就要寫在括號里面加 , nativeQuery = true
4、Dto類要有getter和setter、構造方法
5、自定義的查詢方法不能用自帶的Pageable參數,如果要分頁需要自己寫分頁語句。使用框架自帶的分頁查詢泛型必須是數據庫存在的實體
@Transactional @Query(value = "select new com.famessoft.oplus.cac.domain.AuditJobDto(id,templateName,createdBy,createdAt,endedAt,auditParams,jobStatus) " + "from AuditJob order by ?3 ?4 limit ?1,?2") @Modifying List<AuditJobDto> findAuditDtoByPage(String start,String end,String orderCol,String order);//這里的end是start+length
這里使用了DTO,要寫包名,不然會不認識
注意,泛型那里是返回沒有DTO的實體,這樣子自己就回映射(注意字段名一定要對應)
這里不是自定義的方法,所以不用寫@modifing,這是根據jpa的標准語法來寫的
@Query(value = "select new com.famessoft.oplus.cac.domain.AuditJobDto(job.id,job.templateName,job.createdBy,job.createdAt,job.endedAt,job.auditParams,job.jobStatus) " + "from AuditJob job ") Page<AuditJob> findAuditJobByPage(Pageable pageable);
帶分頁的查詢和過濾
@PostMapping("/jobs/page") @ResponseBody public DataTables getAllTestPages(@RequestParam(value = "start", defaultValue = "0") Integer start, @RequestParam(value = "length", defaultValue = "10") Integer length, HttpServletRequest request) { String search = request.getParameter("search[value]"); //針對一個字段排序的 String orderColumn = request.getParameter("order[0][column]"); String order = request.getParameter("order[0][dir]"); //給出默認排序的字段 String sortCol = null; Sort sort = null; //獲取排序字段 if (orderColumn != null && orderColumn != "") { //獲取datatable排序列(從0開始) int orderCol = Integer.valueOf(orderColumn); sortCol = request.getParameter("columns[" + orderCol + "][data]"); if (order != null) { if (order.toUpperCase().equals(Sort.Direction.DESC)) { sort = new Sort(Sort.Direction.DESC, sortCol); } else if (order.toUpperCase().equals(Sort.Direction.ASC)) { sort = new Sort(Sort.Direction.ASC, sortCol); } } } DataTables dataTables = new DataTables(); Pageable pageable = new PageRequest(start / length, length, sort); Page<AuditJob> page = auditJobRepository.findAuditJobByPage(pageable); if (search == null || search.equals("")) { dataTables.setData(page.getContent()); dataTables.setRecordsTotal(page.getTotalElements()); dataTables.setRecordsFiltered(page.getTotalElements()); return dataTables; } else { //過濾查詢 search = "%" + search + "%"; List<AuditJobDto> list = auditJobRepository.findAuditDtoLikeByPage(search); Page<AuditJob> pageBySearch = auditJobRepository.findAuditJobLikeByPage(search,pageable); dataTables.setData(pageBySearch.getContent()); dataTables.setRecordsTotal(page.getTotalElements());//這是數據總的條數 dataTables.setRecordsFiltered(pageBySearch.getTotalElements());//過濾查詢之后的總數 return dataTables; } }
上面那樣寫其實有點傻,因為碰到了很多問題,因為datatable會吧對象的每個值拆分成每個鍵值對來傳(現在不能回顯了),不過類似於
obj={a:1,b:2}傳到后台不是obj=>{a:1,b:2}
變成了obj[a]=1
obj[b]=2
這樣的值,而且如果使用get方式傳遞的話中括號還會被轉義,根本取不到值,因為key被轉義了,所以我換成了post方式傳遞,取值的方法很笨,但是我還沒查到
java針對datatable標准的接收方法,好的一點是,datatable傳值的方式是不會變的,所以這樣取datatable的值也不會出錯,只是代碼看起來不是很舒服而已
sql查詢語句
這里寫了對多字段的模糊查詢,所以寫了contat函數,但是這個函數針對模糊查詢字段等於null的話,這條數據就不會被查詢出來,所以需要用ifnull,
還有個小問題,寫了IFNULL函數之后,編譯會報錯,但是不用管它,這個會正常運行的
https://blog.csdn.net/yaoyao9565/article/details/51305854
@Query(value = "select new com.famessoft.oplus.cac.domain.AuditJobDto(job.id,job.templateName,job.createdBy,job.createdAt,job.endedAt,job.auditParams,job.jobStatus) " + "from AuditJob job where concat(IFNULL(templateName,'') ,IFNULL(createdBy,''),IFNULL(createdAt,''),IFNULL(endedAt,''),IFNULL(auditParams,''),IFNULL(jobStatus,'')) like ?1 ") Page<AuditJob> findAuditJobLikeByPage(String search,Pageable pageable);
注:
我如果重寫findAll()或者自定義查詢然后只取部分的屬性,會導致我調用findOne的時候也會只取那些屬性。但是后面好像又好了,有點莫名其妙