Mybatis (八) Mybatis整合PageHelper實現分頁


整合PageHelper實現分頁

由於為了后續使用SpringBoot,本人還是推薦使用Java配置類來操作,但是這里還是提一下XML配置。(本文項目基於第六節Mybatis集成Spring操作)

XML配置方式

使用XML文件來配置Mybatis的PageHelper分頁插件:

mybatis-configuration:(mybatis的全局配置文件)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <!--配置開啟自動匹配駝峰-->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
	<!--配置PageHelper分頁插件攔截器-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <property name="offsetAsPageNum" value="true"/>
            <property name="helperDialect" value="mysql"/>
            <property name="rowBoundsWithCount" value="true"/>
            <property name="reasonable" value="true"/>
        </plugin>
    </plugins>
</configuration>

Java配置類方式

完整的配置類:

@Configuration //標注為一個配置類
@PropertySource(value = "classpath:application.properties") //加載屬性文件
@ComponentScan(basePackages = "com.ooyhao.mybatis")  //組件掃描
@MapperScan(basePackages = {"com.ooyhao.mybatis.mapper"})  //mapper文件的掃描
@EnableTransactionManagement //開啟事務管理
public class AppConfig {

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.driver}")
    private String driverClassName;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Value("${mybatis.configuration}")
    private String mybatisConfiguration;

    @Value("${mybatis.mapperLocations}")
    private String mybatisMapperLocations;

    @Value("${mybatis.typeAliasesPackage}")
    private String mybatisTypeAliasesPackage;

    /*配置數據源*/
    @Bean
    public DataSource dataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(url);
        druidDataSource.setDriverClassName(driverClassName);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        return druidDataSource;
    }

    @Bean
    public PageInterceptor pageInterceptor(){
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        /*4.0.0版本之后可以不用配置*/
        properties.setProperty("helperDialect","mysql");
        /*默認為false,會將RowBounds第一個參數offset當成pageNum頁面使用
        * 和startPage中的pageNum效果一樣*/
        properties.setProperty("offsetAsPageNum","true");
        /*RowBounds方式是否做count查詢 默認false*/
        properties.setProperty("rowBoundsWithCount","true");
        /*分頁合理化,true開啟,如果分頁參數不合理會自動修正。默認false不啟用*/
        properties.setProperty("reasonable","true");
        /*是否允許接口方法參數來傳遞分頁參數 默認false*/
        properties.setProperty("supportMethodsArguments","true");
        pageInterceptor.setProperties(properties);
        /*當設置為true的時候,如果pageSize設置為0(或RowBounds的limit=0),就不執行分頁*/
        properties.setProperty("pageSizeZero","true");
        return pageInterceptor;
    }

    /*Mybatis的全局配置*/
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        /*配置Mybatis的全局配置文件*/
        ClassPathResource resource = new ClassPathResource(mybatisConfiguration);
        sqlSessionFactoryBean.setConfigLocation(resource);
        /*配置Mapper.xml文件的路徑*/
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources(mybatisMapperLocations);
        sqlSessionFactoryBean.setMapperLocations(resources);
        /*配置別名包*/
        sqlSessionFactoryBean.setTypeAliasesPackage(mybatisTypeAliasesPackage);
        /*設置數據源,位置有要求,需要在下面幾項之前*/
        sqlSessionFactoryBean.setDataSource(dataSource);
        /*將PageHelper分頁插件以攔截器的形式配置*/
        sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageInterceptor()});
        /*配置駝峰命名*/
        sqlSessionFactoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        /*配置日志類*/
        sqlSessionFactoryBean.getObject().getConfiguration().setLogImpl(StdOutImpl.class);
        /*設置開啟緩存*/
        sqlSessionFactoryBean.getObject().getConfiguration().setCacheEnabled(true);
        return sqlSessionFactoryBean;
    }

    /*配置數據源事務管理器,需要將數據源注入*/
    @Bean
    public DataSourceTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager transactionManager =
                new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
}

提示

  • 添加了PageInterceptor 組件
  • 通過 sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageInterceptor()});設置到SqlSessionFactoryBean中

開啟了這個properties.setProperty("supportMethodsArguments","true");則表示可以通過Mapper來進行參數傳遞,實現分頁,如下:

List<Role> findByPage(@Param("pageNum") int pageNum,@Param("pageSize") int pageSize);

xml文件不需要修改,只需要在參數上添加形參即可。

PageHelper的PageInterceptor的參數說明:一下是PageParams類中的setProperties方法的源碼:

public void setProperties(Properties properties) {
    //offset作為PageNum使用
    String offsetAsPageNum = properties.getProperty("offsetAsPageNum");
    this.offsetAsPageNum = Boolean.parseBoolean(offsetAsPageNum);
    //RowBounds方式是否做count查詢
    String rowBoundsWithCount = properties.getProperty("rowBoundsWithCount");
    this.rowBoundsWithCount = Boolean.parseBoolean(rowBoundsWithCount);
    //當設置為true的時候,如果pagesize設置為0(或RowBounds的limit=0),就不執行分頁
    String pageSizeZero = properties.getProperty("pageSizeZero");
    this.pageSizeZero = Boolean.parseBoolean(pageSizeZero);
    //分頁合理化,true開啟,如果分頁參數不合理會自動修正。默認false不啟用
    String reasonable = properties.getProperty("reasonable");
    this.reasonable = Boolean.parseBoolean(reasonable);
    //是否支持接口參數來傳遞分頁參數,默認false
    String supportMethodsArguments = properties.getProperty("supportMethodsArguments");
    this.supportMethodsArguments = Boolean.parseBoolean(supportMethodsArguments);
    //默認count列
    String countColumn = properties.getProperty("countColumn");
    if(StringUtil.isNotEmpty(countColumn)){
      this.countColumn = countColumn;
    }
    //當offsetAsPageNum=false的時候,不能
    //參數映射
    PageObjectUtil.setParams(properties.getProperty("params"));
}

測試:

下面是測試結果,以及獲取PageInfo中的各個參數。

public class AppTest {
    AnnotationConfigApplicationContext context = null;
    @Before
    public void init(){
        context = new AnnotationConfigApplicationContext(AppConfig.class);
    }

    @Test
    public void testFindByPage(){

        RoleService bean = context.getBean(RoleService.class);
        /*是否需要計算總條數*/
        List<Role> page = bean.findByPage(2, 2, true);
        PageInfo<Role> pageInfo = new PageInfo<>(page);
        //返回的是Page對象,Page是ArrayList的子類。由於Page重寫了toString方法
        List<Role> list = pageInfo.getList();
        System.out.println(JSONObject.toJSONString(list));
        System.out.println(JSONObject.toJSON(list));
        //SQL查詢的數據總條數
        System.out.println("total:"+pageInfo.getTotal());//22
        //總分頁數
        System.out.println("pages:"+pageInfo.getPages());//8
        //自動生成一個分頁導航,大小為8(如果滿足)[1, 2, 3, 4, 5, 6, 7, 8]
        System.out.println("navigatepageNums:"+Arrays.toString(pageInfo.getNavigatepageNums()));
        //分頁導航的第一頁
        System.out.println("navigateFirstPage:"+pageInfo.getNavigateFirstPage());//1
        //分頁導航的最后一頁
        System.out.println("navigateLastPage:"+pageInfo.getNavigateLastPage());//8
        //分頁導航的總頁數
        System.out.println("navigatePages:"+pageInfo.getNavigatePages());//8
        //當前頁
        System.out.println("pageNum:"+pageInfo.getPageNum());//2
        //當前頁的上一頁
        System.out.println("prePage:"+pageInfo.getPrePage());//1
        //當前頁的下一頁
        System.out.println("nextPage:"+pageInfo.getNextPage());//3
        //每頁的數據條數
        System.out.println("pageSize:"+pageInfo.getPageSize());//3
        //當前頁的開始行號
        System.out.println("startRow:"+pageInfo.getStartRow());//4
        //當前頁的結束行號
        System.out.println("endRow:"+pageInfo.getEndRow());//6
    }
}

提示:

List list = pageInfo.getList();我們通過打印這個list對象是無法正常打印出Role對象的數據,是因為Page對象繼承自ArrayList,並且重寫了toString方法。我們可以通過迭代循環打印出來。如下圖:

​ 這里由於循環打印才能看到Role對象的真實面部,個人覺得麻煩,所以使用了fastJson格式化為Json,但是發現一個之前沒有留意的問題:

​ 通過上面打印出的結果可以發現,list既然是Page對象,但是我們可以看到Page類中有諸多屬性,為何通過JSON格式化工具之后,就沒有了呢?通過查詢fastJson的toJson源碼就可以發現奧秘了,如下:

public static Object toJSON(Object javaObject, SerializeConfig config) {
        ......
        if (javaObject instanceof Collection) {
            Collection<Object> collection = (Collection<Object>) javaObject;
            JSONArray array = new JSONArray(collection.size());
            for (Object item : collection) {
                Object jsonValue = toJSON(item, config);
                array.add(jsonValue);
            }
            return array;
        }
      	......
        String text = JSON.toJSONString(javaObject);
        return JSON.parse(text);
}

​ 里面有這樣一個判斷,如果對象是Collection或其子類,則強轉為Collection,所以我們會發現,在使用JSONObject.toJson或是toJsonString的時候,不管是ArrayList還是Page中的屬性都沒有了,這是因為取的是Collection。對於數據存儲,需要進一步研究Collection系列集合,暫不涉及。

Page對象源碼

下面我們看一下Page對象源碼:

public class Page<E> extends ArrayList<E> implements Closeable {
    private static final long serialVersionUID = 1L;

    /**
     * 頁碼,從1開始
     */
    private int pageNum;
    /**
     * 頁面大小
     */
    private int pageSize;
    /**
     * 起始行
     */
    private int startRow;
    /**
     * 末行
     */
    private int endRow;
    /**
     * 總數
     */
    private long total;
    /**
     * 總頁數
     */
    private int pages;
    /**
     * 包含count查詢
     */
    private boolean count = true;
    /**
     * 分頁合理化
     */
    private Boolean reasonable;
    /**
     * 當設置為true的時候,如果pagesize設置為0(或RowBounds的limit=0),就不執行分頁,返回全部結果
     */
    private Boolean pageSizeZero;
    /**
     * 進行count查詢的列名
     */
    private String countColumn;
    /**
     * 排序
     */
    private String orderBy;
    /**
     * 只增加排序
     */
    private boolean orderByOnly;

    public Page() {
        super();
    }

    public Page(int pageNum, int pageSize) {
        this(pageNum, pageSize, true, null);
    }

    public Page(int pageNum, int pageSize, boolean count) {
        this(pageNum, pageSize, count, null);
    }

    private Page(int pageNum, int pageSize, boolean count, Boolean reasonable) {
        super(0);
        if (pageNum == 1 && pageSize == Integer.MAX_VALUE) {
            pageSizeZero = true;
            pageSize = 0;
        }
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.count = count;
        calculateStartAndEndRow();
        setReasonable(reasonable);
    }

    /**
     * int[] rowBounds
     * 0 : offset
     * 1 : limit
     */
    public Page(int[] rowBounds, boolean count) {
        super(0);
        if (rowBounds[0] == 0 && rowBounds[1] == Integer.MAX_VALUE) {
            pageSizeZero = true;
            this.pageSize = 0;
        } else {
            this.pageSize = rowBounds[1];
            this.pageNum = rowBounds[1] != 0 
              ? (int) (Math.ceil(((double) rowBounds[0] + rowBounds[1]) / rowBounds[1])) : 0;
        }
        this.startRow = rowBounds[0];
        this.count = count;
        this.endRow = this.startRow + rowBounds[1];
    }

    public List<E> getResult() {
        return this;
    }

    public int getPages() {
        return pages;
    }

    public Page<E> setPages(int pages) {
        this.pages = pages;
        return this;
    }

    public int getEndRow() {
        return endRow;
    }

    public Page<E> setEndRow(int endRow) {
        this.endRow = endRow;
        return this;
    }

    public int getPageNum() {
        return pageNum;
    }

    public Page<E> setPageNum(int pageNum) {
        //分頁合理化,針對不合理的頁碼自動處理
        this.pageNum = ((reasonable != null && reasonable) && pageNum <= 0) ? 1 : pageNum;
        return this;
    }

    public int getPageSize() {
        return pageSize;
    }

    public Page<E> setPageSize(int pageSize) {
        this.pageSize = pageSize;
        return this;
    }

    public int getStartRow() {
        return startRow;
    }

    public Page<E> setStartRow(int startRow) {
        this.startRow = startRow;
        return this;
    }

    public long getTotal() {
        return total;
    }

    public void setTotal(long total) {
        this.total = total;
        if (total == -1) {
            pages = 1;
            return;
        }
        if (pageSize > 0) {
            pages = (int) (total / pageSize + ((total % pageSize == 0) ? 0 : 1));
        } else {
            pages = 0;
        }
        //分頁合理化,針對不合理的頁碼自動處理
        if ((reasonable != null && reasonable) && pageNum > pages) {
            pageNum = pages;
            calculateStartAndEndRow();
        }
    }

    public Boolean getReasonable() {
        return reasonable;
    }

    public Page<E> setReasonable(Boolean reasonable) {
        if (reasonable == null) {
            return this;
        }
        this.reasonable = reasonable;
        //分頁合理化,針對不合理的頁碼自動處理
        if (this.reasonable && this.pageNum <= 0) {
            this.pageNum = 1;
            calculateStartAndEndRow();
        }
        return this;
    }

    public Boolean getPageSizeZero() {
        return pageSizeZero;
    }

    public Page<E> setPageSizeZero(Boolean pageSizeZero) {
        if (pageSizeZero != null) {
            this.pageSizeZero = pageSizeZero;
        }
        return this;
    }
    public String getOrderBy() {
        return orderBy;
    }

    public <E> Page<E> setOrderBy(String orderBy) {
        this.orderBy = orderBy;
        return (Page<E>) this;
    }

    public boolean isOrderByOnly() {
        return orderByOnly;
    }

    public void setOrderByOnly(boolean orderByOnly) {
        this.orderByOnly = orderByOnly;
    }

    /**
     * 計算起止行號
     */
    private void calculateStartAndEndRow() {
        this.startRow = this.pageNum > 0 ? (this.pageNum - 1) * this.pageSize : 0;
        this.endRow = this.startRow + this.pageSize * (this.pageNum > 0 ? 1 : 0);
    }

    public boolean isCount() {
        return this.count;
    }

    public Page<E> setCount(boolean count) {
        this.count = count;
        return this;
    }

    /**
     * 設置頁碼
     *
     * @param pageNum
     * @return
     */
    public Page<E> pageNum(int pageNum) {
        //分頁合理化,針對不合理的頁碼自動處理
        this.pageNum = ((reasonable != null && reasonable) && pageNum <= 0) ? 1 : pageNum;
        return this;
    }

    /**
     * 設置頁面大小
     *
     * @param pageSize
     * @return
     */
    public Page<E> pageSize(int pageSize) {
        this.pageSize = pageSize;
        calculateStartAndEndRow();
        return this;
    }

    /**
     * 是否執行count查詢
     *
     * @param count
     * @return
     */
    public Page<E> count(Boolean count) {
        this.count = count;
        return this;
    }

    /**
     * 設置合理化
     *
     * @param reasonable
     * @return
     */
    public Page<E> reasonable(Boolean reasonable) {
        setReasonable(reasonable);
        return this;
    }

    /**
     * 當設置為true的時候,如果pagesize設置為0(或RowBounds的limit=0),就不執行分頁,返回全部結果
     *
     * @param pageSizeZero
     * @return
     */
    public Page<E> pageSizeZero(Boolean pageSizeZero) {
        setPageSizeZero(pageSizeZero);
        return this;
    }

    /**
     * 指定 count 查詢列
     *
     * @param columnName
     * @return
     */
    public Page<E> countColumn(String columnName) {
        this.countColumn = columnName;
        return this;
    }


    /**
     * 轉換為PageInfo
     *
     * @return
     */
    public PageInfo<E> toPageInfo() {
        PageInfo<E> pageInfo = new PageInfo<E>(this);
        return pageInfo;
    }

    public <E> Page<E> doSelectPage(ISelect select) {
        select.doSelect();
        return (Page<E>) this;
    }

    public <E> PageInfo<E> doSelectPageInfo(ISelect select) {
        select.doSelect();
        return (PageInfo<E>) this.toPageInfo();
    }

    public long doCount(ISelect select) {
        this.pageSizeZero = true;
        this.pageSize = 0;
        select.doSelect();
        return this.total;
    }

    public String getCountColumn() {
        return countColumn;
    }

    public void setCountColumn(String countColumn) {
        this.countColumn = countColumn;
    }

    @Override
    public String toString() {
        return "Page{" +
                "count=" + count +
                ", pageNum=" + pageNum +
                ", pageSize=" + pageSize +
                ", startRow=" + startRow +
                ", endRow=" + endRow +
                ", total=" + total +
                ", pages=" + pages +
                ", reasonable=" + reasonable +
                ", pageSizeZero=" + pageSizeZero +
                '}';
    }

    @Override
    public void close() {
        PageHelper.clearPage();
    }
}

最后

如果覺得不錯的話,那就關注一下小編哦!一起交流,一起學習


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM