前言
反射可以獲取任何一個已知名稱的類中定義的屬性蒜危,不論它是公有還是私有潮酒!使用反射你會發(fā)現(xiàn)原來java可以如此靈活,你不用再無窮無盡地寫循環(huán)磨镶、定義變量溃蔫,它會讓你的代碼簡潔大方,耦合性更低琳猫。我本身剛剛接觸到反射伟叛,希望通過一個分頁功能的實現(xiàn)和大家一起去學習應用反射,在編程的不歸路上越走越遠脐嫂。
很多人在mybatis開發(fā)中都喜歡使用pagehelper當做自己的分頁插件统刮,但是這個插件在使用過程中一直存在一個問題——多表關聯(lián)一對多的情況下分頁會出現(xiàn)不準確的情況紊遵,出現(xiàn)這種情況的原因是當你的查詢語句主表和附表之間是一對多的關系時,當sql語句查詢完成后mybatis會以主表為主將附表信息封裝到你定義的主表對應的字段中侥蒙。本人也曾嘗試去仔細閱讀pageheloer的api文檔暗膜,但是找來找去耽誤了很長時間也沒找到具體行之有效的方法。索性自己封裝一個pageutil鞭衩,總體來說效果不錯~
在案例中我們使用的前端框架是vue学搜,這里不做過多的介紹,如果大家感興趣我會在后期寫一篇使用vue-cli搭建vue項目的博客论衍。后端是springboot瑞佩。
首先封裝一個pageBO,用來存放返回前端的數(shù)據(jù)
@DatapublicclassPageBO{privateintsize;//list長度privateinttotal;//總查詢數(shù)privateintstartRow;//開始條數(shù)privateintendRow;//結(jié)束條數(shù)privateintfirstPage;//第一頁頁碼privateintlastPage;//最后一頁頁碼privateintpages;//頁數(shù)privateint[]navigatepageNums;//頁碼數(shù)組privateintpageNum;//當前頁碼privateintpageSize;//每頁數(shù)據(jù)量Object list;//數(shù)據(jù)列表}
pageUtil源碼:
importcom.easy.xbo.PageBO;importorg.apache.poi.ss.formula.functions.T;importjava.lang.reflect.Method;importjava.util.List;publicclassPageUtil{publicstaticPageBOgetPageBOData(Object service,Object param)throwsException{PageBO pageBO=newPageBO();ClassPageclass=service.getClass();ClassParamclass=param.getClass();Method PagemethodSelectCount=Pageclass.getDeclaredMethod("selectCount",Paramclass);//可以通過Method類的invoke方法調(diào)用類方法//查詢總數(shù)坯台,此時注意需要傳遞兩個參數(shù)炬丸,第一個是方法所在的類,第二個是方法需要的參數(shù) //invoke方法第一個參數(shù)是固定的蜒蕾,是方法所在類稠炬,第二個是可選的,是方法所需參數(shù)intcount=Integer.parseInt(PagemethodSelectCount.invoke(service,param)+"");Method ParammethodGet=Paramclass.getDeclaredMethod("getWhere");Object where=ParammethodGet.invoke(param);ClassWhereclass=where.getClass();//第幾頁Method WheremethodPage=Whereclass.getDeclaredMethod("getPage");intpage=Integer.parseInt(WheremethodPage.invoke(where)+"");//每頁條數(shù)Method WheremethodRows=Whereclass.getDeclaredMethod("getRows");intpageSize=Integer.parseInt(WheremethodRows.invoke(where)+"");//計算本頁從哪一條數(shù)據(jù)開始intstartRow=(page-1)*pageSize;Method WheremethodStartrow=Whereclass.getDeclaredMethod("setStartrow",int.class);WheremethodStartrow.invoke(where,startRow);//計算頁數(shù)intpages=count/pageSize;if(count%pageSize>0){pages++;}//存放頁碼的數(shù)組int[]NavigatepageNums=newint[pages];for(inti=1;i<=pages;i++){NavigatepageNums[i-1]=i;}pageBO.setTotal(count);pageBO.setStartRow(startRow+1);pageBO.setFirstPage(1);pageBO.setPages(pages);pageBO.setLastPage(pages);pageBO.setNavigatepageNums(NavigatepageNums);pageBO.setPageSize(pageSize);pageBO.setPageNum(page);Method PagemethodSelectPage=Pageclass.getDeclaredMethod("selectPage",Paramclass);Object pagelist=PagemethodSelectPage.invoke(service,param);pageBO.setList(pagelist);pageBO.setSize(((List)pagelist).size());intendRow=startRow+pageBO.getSize();pageBO.setEndRow(endRow);returnpageBO;}}
Object 類型的 service 中必須有兩個方法:一個是 selectCount 用來查詢分頁的total咪啡,也就是所有符合查詢條件的數(shù)據(jù)總數(shù)首启;一個是 selectPage 這個方法查詢具體數(shù)據(jù)。
Object 類型的 param 包含兩個參數(shù):一個是where瑟匆;一個是xdo闽坡。(具體結(jié)構(gòu)參照)
然后就是對反射的使用(具體參照)
以上是公用部分的代碼
下面舉個栗子~~:
公司與員工的關系栽惶,一個公司有多個員工愁溜,屬于一對多的關系,這里插一句lombok很好用外厂,有興趣的小伙伴可以了解一下
CompanyDO源碼:
```java
package com.easy.xdo;
import lombok.Data;
@Data
public class CompanyDO {
//演示公司類
private String id;
private String name;
private String address;
private List<EmployeDO> employes;
}
```
CompanyWhere 源碼:
```java
package com.easy.xdo;
import lombok.Data;
@Data
public class CompanyWhere extends CompanyDO{
/**
? ? * page -1 默認不分頁
? ? */
? ? private int page;
? ? private int rows;
? ? private int startrow;
? ? private String suffix;
}
```
CompanyParam 源碼:
```java
package com.easy.xdo;
import lombok.Data;
@Data
public class CompanyParam {
private CompanyDO xdo;
private CompanyWhere where;
}
```
EmployeDO源碼:
```java
package com.easy.xdo;
import lombok.Data;
@Data
public class EmployeDO {
? ? //演示員工類
private String id;
private String name;
private String age;
private String companyid;
}
CompanyController源碼:
package com.easy.controller;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.easy.service.CompanyService;
import com.easy.util.PageUtil;
import com.easy.xbo.PageBO;
import com.easy.xdo.CompanyParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import io.swagger.annotations.ApiOperation;
@Api("API-公司接口")
@RestController
@RequestMapping("api/v1/company")
public class CompanyController {
@Autowired
? ? private CompanyService companyService;
@ApiOperation(value = "分頁查詢")
? ? @PostMapping("/page")
? ? public PageBO page() throws Exception{
CompanyParam param=new CompanyParam();
? ? ? ? return PageUtil.getPageBOData(companyService,param);
? ? }
}
CompanyService 源碼:
package com.easy.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.easy.dao.CompanyDAO;
import com.easy.xdo.CompanyDO;
import com.easy.xdo.CompanyParam;
public class CompanyService {
@Autowired
private CompanyDAO companyDAO;
public List<CompanyDO> selectPage(CompanyParam param){
? ? ? ? return companyDAO.selectList(param);
? ? }
? ? public int selectCount(CompanyParam param){
? ? ? ? return companyDAO.selectCount(param);
? ? }
}
dao源碼
package com.easy.dao;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.easy.xdo.CompanyDO;
import com.easy.xdo.CompanyParam;
@Repository
public interface CompanyDAO {
List<CompanyDO> selectList(CompanyParam param);
? ? int? selectCount(CompanyParam param);
}
xml源碼
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.easy.dao.CompanyDAO">
? <resultMap id="BaseResultMap" type="com.easy.xdo.CompanyDO">
? ? <id column="id" property="id" />
? ? <result column="name" property="name" />
? ? <result column="address" property="address" />
? ? <collection property="employes" ofType="com.easy.xdo.EmployeDO">
? ? ? <id column="eid" property="id" />
? ? ? <result column="ename" property="name"/>
? ? ? <result column="age" property="age"/>
? ? </collection>
? </resultMap>
? <sql id="sqlBase">
? ? c.id,c.name,c.address,e.id as eid,e.name as ename,e.age
? </sql>
? <sql id="WhereModelSql">
? ? <if test="where != null">
? ? ? <where>
? ? ? ? <if test="where.id != null and where.id != ''"> AND c.id=#{where.id} </if>
? ? ? ? <if test="where.name != null and where.name != ''"> AND c.name=#{where.name} </if>
? ? ? ? <if test="where.address != null and where.address != ''"> AND c.address=#{where.address} </if>
? ? ? </where>
? ? </if>
? </sql>
? <select id="selectList" resultMap="BaseResultMap" parameterType="com.easy.xdo.CompanyParam">
? ? select
? ? <include refid="sqlBase" />
? ? from company c left join employe e on? c.id=e.companyid?
? ? where c.id in (select page.id from (select id from company
? ? <include refid="WhereModelSql" />? limit #{where.startrow},#{where.rows})
? ? page)
? </select>
? <select id="selectCount" resultType="java.lang.Integer" parameterType="com.easy.xdo.CompanyParam">
? ? select
? ? count(c.id)
? ? from company
? ? <include refid="WhereModelSql" />
? </select>
</mapper>
這里特殊說明一下in語句子語句中不能使用limit冕象,但是孫語句中可以使用,很蛋疼所以多包了一層汁蝶,sql語句這里大家可以根據(jù)自己的情況隨意寫渐扮,只要最后傳參進去出來的數(shù)據(jù)準確就ok了