之前只用過單數據源下的分頁插件,而且幾乎不用配置。一個靜態方法就能搞定。
PageHelper.startPage(pageNum, pageSize);
后來使用了多數據源(不同的數據庫),PageHelper分頁插件需要設定一個默認的數據庫,mysql、oracle或者其他。
但是又不能實時切換,導致請求的第一個類型數據庫的請求都可以繼續請求,而其他的數據庫的請求因為sql語句在不同數據庫的count和分頁語句不同報錯。
解決思路是
①配置先配置多數據源,再配置多個SqlSessionFactory使用不同的數據源,SqlSessionFactory同時指定某些dao層接口(或者mapper),此時不同的dao層就可以訪問不同數據源
②在每個SqlSessionFactory中配置一個分頁插件
第一步驟中的多數據源配置很多博文都有記錄,在此不再重復寫,我配置的時候參考的是這個鏈接
http://blog.csdn.net/neosmith/article/details/61202084
他提供了一個多數據源手動配置,一個自動配置方案。因為我們要在多數據源下另外配置分頁插件,所以選用手動配置方案。
重點講第二步驟:
一、多數據源下配置分頁插件
如果你使用的上邊的配置方案,那么你現在應該有多個SqlSessionFactory的bean。我們重點來看某個SqlSessionFactory bean的配置:
1 @Configuration 2 @MapperScan(basePackages = {"com.firstRest.dao.localLeftjointest"}, sqlSessionFactoryRef = "sqlSessionFactory1") 3 public class MybatisDbAConfig { 4 5 @Autowired 6 @Qualifier("localLeftjointestDataSource") 7 private DataSource ds1; 8 9 @Bean 10 public SqlSessionFactory sqlSessionFactory1() throws Exception { 11 SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); 12 factoryBean.setDataSource(ds1); // 使用localLeftjointest數據源, 連接leftjointest庫 13 14 //分頁插件 15 Interceptor interceptor = new PageInterceptor(); 16 Properties properties = new Properties(); 17 properties.setProperty("helperDialect", "mysql"); 18 properties.setProperty("offsetAsPageNum", "true"); 19 properties.setProperty("rowBoundsWithCount", "true"); 20 properties.setProperty("reasonable", "true"); 21 properties.setProperty("supportMethodsArguments","true"); 22 properties.setProperty("params","pageNum=pageNumKey;pageSize=pageSizeKey;"); 23 interceptor.setProperties(properties); 24 factoryBean.setPlugins(new Interceptor[] {interceptor}); 25 26 return factoryBean.getObject(); 27 28 } 29 30 @Bean 31 public SqlSessionTemplate sqlSessionTemplate1() throws Exception { 32 SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory1()); // 使用上面配置的Factory 33 return template; 34 } 35 }
多出來的代碼就是我們需要添加的地方,我們來看一下到底干了些什么:
①新建了一個PageInterceptor,因為Mybatis允許在已經映射語句執行過程中某一點進行攔截調用,而PageHelper就是在這進行分頁操作的
②新建一個屬性,並添加一些屬性值,這些屬性值里重要的是:
(1)helperDialect 數據庫方言:數據庫是什么就寫什么就行 mysql、sqlserver、oracle、db2 這樣的,詳情參考 https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/en/HowToUse.md
(2)supportMethodsArguments 是否支持參數方式進行分頁:寫true就行了,后邊寫原因
(3)params 支持了那些參數:pageNum=pageNumKey;pageSize=pageSizeKey。分別對應了分頁頁碼,分頁大小。
需要注意的是:
有些博文中寫的是在①步驟中新建一個PageHelper對象,設置PageHelper的屬性,然后添加到Plugins里面去,現在已經不支持這種寫法了! 現在就是要用PageInterceptor!
(2)(3)中設置的是插件是用方案配置,如果這樣設置的話,在dao層(或者mapper中)接口同時出現pageNumKey 和 pageSizeKey 參數,這個方法就會被分頁。為什么使用這個方法呢,我們之后講,先這么寫就對了。
單個SqlSessionFactory配置好了,其他的SqlSessionFactory在配置分頁插件的時候只需要把helperDialect 修改成另外一個數據源數據庫類型即可。
二、如何寫dao層接口
上邊我們設置了supportMethodsArguments 和params,如何使分頁插件在我們調用dao層方法的時候生效呢?
代碼如下:
1 @Repository 2 public interface JlzxDao { 3 @Select(value = "Select * from ${table_name} order by id") 4 @ResultType(HashMap.class) 5 List<HashMap> getAll(@Param("table_name") String tableName, 6 @Param("pageNumKey") int pageNum, 7 @Param("pageSizeKey") int pageSize); 8 }
重點看標紅的參數,我並沒有把這兩個參數在sql中使用,但把兩個參數寫了進去。這樣同時出現pageNumKey 和 pageSizeKey 參數,這個方法就會被分頁。
這樣Dao層咋調用的時候多傳兩個分頁參數過去就可以自動分頁了。
三、為何選用這種參數方式使用分頁
在單數據源的時候,我使用的是靜態方法,即本文最開始的那行代碼進行標示,使下一個查詢語句進行分頁。
但使用這種靜態方法時,在service層(或者controller層)判斷數據源來自哪里之后使用下邊的語句,這是我之前的service層的寫法:
1 @Service("BaseService") 2 public class BasePagingService implements PagingService{ 3 @Autowired 4 private JlzxDao jlzxDao; 5 @Autowired 6 private LeftjointestDao leftjointestDao; 7 8 @Override 9 public PageInfo<HashMap> selectByPage(String dbName,String tableName,int currentPage, int pageSize){ 10 if(dbName.equals("leftjointest")){ 11 PageHelper.startPage(currentPage, pageSize); 12 return new PageInfo<>(leftjointestDao.getAll(tableName)); 13 } 14 else if(dbName.equals("jlzx")){ 15 PageHelper.startPage(currentPage, pageSize); 16 return new PageInfo<>(jlzxDao.getAll(tableName)); 17 } 18 return null; 19 20 } 21 }
這樣的方法會報錯:在系統中發現了多個分頁插件,請檢查系統配置!
所以換了參數直接寫在dao層方法中的用法。
我的項目鏈接如下:
https://github.com/Jaccccccccccccccccccccccccccccck/firstREST
如有錯誤,還望指正!