Mybatis+MySQL動態分頁查詢


https://blog.csdn.net/qq_34137397/article/details/63289621

 

mybatis有兩種分頁方法

1、內存分頁,也就是假分頁。本質是查出所有的數據然后根據游標的方式,截取需要的記錄。如果數據量大,開銷大和內存溢出。

第二中是,真正的物理分頁

還有一種是使用分頁攔截器實現的

 

常見的數據分頁有哪幾種實現??基於數組的分頁實現?基於sql語句的分頁實現?還是通過攔截器進行數據分頁功能?還是通過RowBounds參數進行物理分頁?幾種都是常用的分頁實現原理

 

一.借助數組進行分頁

原理:進行數據庫查詢操作時,獲取到數據庫中所有滿足條件的記錄,保存在應用的臨時數組中,再通過List的subList方法,獲取到滿足條件的所有記錄。

二.借助Sql語句進行分頁,物理分頁

實現:通過sql語句實現分頁也是非常簡單的,只是需要改變我們查詢的語句就能實現了,即在sql語句后面添加limit分頁語句。

首先還是在StudentMapper接口中添加sql語句查詢的方法,如下:

List<Student> queryStudentsBySql(Map<String,Object> data);
然后在StudentMapper.xml文件中編寫sql語句通過limiy關鍵字進行分頁:

 <select id="queryStudentsBySql" parameterType="map" resultMap="studentmapper">
        select * from student limit #{currIndex} , #{pageSize}
</select>
接下來還是在IStuService接口中定義方法,並且在StuServiceIml中對sql分頁實現。

List<Student> queryStudentsBySql(int currPage, int pageSize);
 @Override
    public List<Student> queryStudentsBySql(int currPage, int pageSize) {
        Map<String, Object> data = new HashedMap();
        data.put("currIndex", (currPage-1)*pageSize);
        data.put("pageSize", pageSize);
        return studentMapper.queryStudentsBySql(data);
    }
sql分頁語句如下:select * from table limit index, pageSize;

 

四.RowBounds實現分頁

原理:通過RowBounds實現分頁和通過數組方式分頁原理差不多,都是一次獲取所有符合條件的數據,然后在內存中對大數據進行操作,實現分頁效果。只是數組分頁需要我們自己去實現分頁邏輯,這里更加簡化而已。

存在問題:一次性從數據庫獲取的數據可能會很多,對內存的消耗很大,可能導師性能變差,甚至引發內存溢出。

適用場景:在數據量很大的情況下,建議還是適用攔截器實現分頁效果。RowBounds建議在數據量相對較小的情況下使用。

簡單介紹:這是代碼實現上最簡單的一種分頁方式,只需要在dao層接口中要實現分頁的方法中加入RowBounds參數,然后在service層通過offset(從第幾行開始讀取數據,默認值為0)和limit(要顯示的記錄條數,默認為java允許的最大整數:2147483647)兩個參數構建出RowBounds對象,在調用dao層方法的時,將構造好的RowBounds傳進去就能輕松實現分頁效果了。

具體操作如下:

dao層接口方法:

//加入RowBounds參數
public List<UserBean> queryUsersByPage(String userName, RowBounds rowBounds);

然后在service層構建RowBounds,調用dao層方法:

  @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.SUPPORTS)
    public List<RoleBean> queryRolesByPage(String roleName, int start, int limit) {
        return roleDao.queryRolesByPage(roleName, new RowBounds(start, limit));
    }

RowBounds就是一個封裝了offset和limit簡單類,如下所示:

public class RowBounds {
    public static final int NO_ROW_OFFSET = 0;
    public static final int NO_ROW_LIMIT = 2147483647;
    public static final RowBounds DEFAULT = new RowBounds();
    private int offset;
    private int limit;

    public RowBounds() {
        this.offset = 0;
        this.limit = 2147483647;
    }

    public RowBounds(int offset, int limit) {
        this.offset = offset;
        this.limit = limit;
    }

    public int getOffset() {
        return this.offset;
    }

    public int getLimit() {
        return this.limit;
    }
}

只需要這兩步操作,就能輕松實現分頁效果了,是不是很神奇。但卻不簡單,內部是怎么實現的??給大家提供一個簡單的思路:RowBounds分頁簡單原理

結論:從上面四種sql分頁的實現方式可以看出,通過RowBounds實現是最簡便的,但是通過攔截器的實現方式是最優的方案。只需一次編寫,所有的分頁方法共同使用,還可以避免多次配置時的出錯機率,需要修改時也只需要修改這一個文件,一勞永逸。而且是我們自己實現的,便於我們去控制和增加一些邏輯處理,使我們在外層更簡單的使用。同時也不會出現數組分頁和RowBounds分頁導致的性能問題。當然,具體情況可以采取不同的解決方案。數據量小時,RowBounds不失為一種好辦法。但是數據量大時,實現攔截器就很有必要了。

到這里,mybatis的分頁原理和全部實現過程都完成了,還有不清楚的可以自己去看一下mybatis的源碼,按照這個思路去閱讀還是比較清晰的。這里只是對插件(攔截器)實現分頁做了個簡單的介紹,只是簡單的分頁功能,還很簡陋。在下一遍博客我們將會實現一個封裝好的、功能齊全的實用性插件。傳送門:mybatis精通之路之插件分頁(攔截器)進階 
最后,希望大家提出寶貴意見,共同學習。

 

1. 使用Map來進行包裝數據實現分頁功能
        1),在SQL語句映射的ResultType返回的是你要查詢得到的實體類
        2),穿進去的參數parameterType是你自己包裝的Map類型
        3),首先你傳進來的參數要和SQL語句中的字段名要保持一致
        4),在實體DAO層還需要把查詢數據的起始下標,和查詢多少條數據都put進Map中

SQL映射:

 <!--查詢所有的用戶信息,用map分頁實現-->
    <select id="getAllMap" resultType="User" parameterType="Map">
        SELECT * FROM user limit #{startIndex},#{pageSize}
    </select>

DAO實現類

//這個是實現分頁查詢功能(用map來實現的第一種方式)
    public List<User> getAll(int currentPage,int pageSize) throws IOException {
        SqlSession  sqlSession = MybatisUtil.getSession();
        Map<String,Integer> map = new HashMap<String, Integer>();
//這個是把當
        map.put("startIndex",(currentPage-1)*pageSize);
        map.put("pageSize",pageSize);
        List<User> list = sqlSession.selectList("UserMapper.getAllMap",map);
        sqlSession.close();
        return list;
    }

測試類


    public static void main(String[] args) throws IOException {
        UserDao userDao = new UserDao();
        //這個傳進來的第一個參數是你要顯示第幾頁的數據,第二是你需要沒頁顯示幾條記錄
        List<User> list = userDao.getAll(2, 3);
        for (User user : list) {
            System.out.println(user.toString());
        }
       }
2. 使用RowBounds來實現分頁
        1),只需要設置一個返回值為User實體類型
        2),RowBounds rowBounds= newRowBounds((currentPage-1)*pageSize,pageSize);
        3),就是上一步多了一個創建一個RowBounds對象,然后需要傳入SQL語句中需要的參數就行了
        4),然后sqlSession在執行selectList的時候把那個rowBounds對象直接傳進去就可以了

SQL的xml映射

   <!--查詢所有用戶的信息,用RowBounds來實現-->
    <select id="getAllRowBounds" resultType="User">
        SELECT *FROM user
    </select>

DAO實現類

 //這個是通過RowBounds來實現查詢功能的分頁操作
    public List<User> getAllRowBounds(int currentPage,int pageSize) throws IOException {
        SqlSession sqlSession = MybatisUtil.getSession();
        /*rowBounds需要的第一個參數就是從數據的哪個下標開始開始查,第二個就是你需要查詢的條數*/
        RowBounds rowBounds= new RowBounds((currentPage-1)*pageSize,pageSize);
        List<User> list = sqlSession.selectList("UserMapper.getAllRowBounds",
                null, rowBounds);
        sqlSession.close();
        return list;
    }

測試類

ublic class TestRowBounds {

    public static void main(String[] args) throws IOException {
        UserDao userDao = new UserDao();
        List<User> list = userDao.getAllRowBounds(1, 3);
        for (User user : list) {
            System.out.println(user.toString());
        }
    }
}

 


免責聲明!

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



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