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()); } } }