Springmvc+mybatis+maven查詢分頁完美封裝版
阿新 • • 發佈:2019-02-14
新專案用的spring mvc 和 mybatis 分頁。研究了一下,集眾家之長然後形成現在的專案。我把分頁部分剝離出來與大家分享。如有不妥的地方歡迎交流拍磚。
單獨做了一個小專案,放到了下載區,如果有用到的朋友可以去下載。
本專案採用了攔截器,就是mybaits自帶的plus功能。將每次select操作都進行攔截。
專案架構如下:
1:首先從cotroller層出發,啥也不說,上程式碼。這個最實惠
[java] view plaincopy
- package com.flydreamer.controller;
- import java.util.HashMap;
- import java.util.Map;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.servlet.ModelAndView;
- import com.flydreamer.logic.UserService;
- import com.flydreamer.page.Page;
- import com.flydreamer.page.PageContext;
- import com.flydreamer.util.web.HandlerResult;
- @Controller
- @RequestMapping("/user.do")
- publicclass UserController {
- @Autowired
- private UserService userService;
- @RequestMapping(params = (
- public ModelAndView listAll(HttpServletRequest request,HttpServletResponse response) {
- //可以將分頁引數獲取封裝,已達到更好的複用效果。
- //page=2&pageSize=10&totalPages=19&totalRows=188
- String pagec = request.getParameter("page");
- String pageSize = request.getParameter("pageSize");
- String totalPages = request.getParameter("totalPages");
- String totalRows = request.getParameter("totalRows");
- //方法1:將分頁引數直接放到mapper介面函式引數中,也可在物件中定義名字為page的屬性,反射一樣可以得到
- //後臺連線直接獲取
- //Page page = new Page();
- //方法2:不用進行map傳參,用ThreadLocal進行傳參,方便沒有侵入性
- PageContext page = PageContext.getContext();
- //請自行驗證
- if(null == pagec)
- {
- page.setCurrentPage(1);
- page.setPageSize(10);
- }
- else{
- page.setCurrentPage(Integer.parseInt(pagec));
- page.setPageSize(Integer.parseInt(pageSize));
- page.setTotalPages(Integer.parseInt(totalPages));
- page.setTotalRows(Integer.parseInt(totalRows));
- }
- page.setPagination(true);
- // 方法1用
- // Map map = new HashMap();
- // map.put("page", page);
- // HandlerResult rs = userService.list(map);
- //方法2用
- HandlerResult rs = userService.list();
- ModelAndView mv = new ModelAndView("/views/show.jsp");
- mv.addObject("userList", rs.getResultObj());
- mv.addObject("page",page);
- return mv;
- }
- }
簡要說明:本文采用兩種方式將page物件傳入到攔截器中。第一種方式是採用引數傳值,不管是用map還是在統一引數物件中名稱為page的屬性都可以在分頁攔截器中得到page的值。第二種方式是用ThreadLocal,對service層沒有侵入性。比較方便。
2:Service層程式碼。沒啥可說的上程式碼
[java] view plaincopy
- package com.flydreamer.logic;
- import java.util.Map;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import com.flydreamer.orm.mapper.UsersMapper;
- import com.flydreamer.util.web.HandlerResult;
- @Service
- publicclass UserService {
- @Autowired
- private UsersMapper usersMappser;
- /**
- * 統一Service出口,方便管理
- * @param map
- * @return
- */
- public HandlerResult list(Map map){
- HandlerResult rs = new HandlerResult();
- rs.setResultObj(usersMappser.list(map));
- return rs;
- }
- /**
- * 採用本地執行緒的方式分頁
- * @return
- */
- public HandlerResult list(){
- HandlerResult rs = new HandlerResult();
- rs.setResultObj(usersMappser.list2());
- return rs;
- }
- public UsersMapper getUsersMappser() {
- return usersMappser;
- }
- publicvoid setUsersMappser(UsersMapper usersMappser) {
- this.usersMappser = usersMappser;
- }
- }
3:mybatis介面
[java] view plaincopy
- package com.flydreamer.orm.mapper;
- import java.util.List;
- import java.util.Map;
- import com.flydreamer.orm.SqlMapper;
- publicinterface UsersMapper extends SqlMapper{
- public List list(Map para);
- public List list2();
- }
4:page的攔截器
[java] view plaincopy
- package com.flydreamer.interceptor;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.List;
- import java.util.Properties;
- import org.apache.ibatis.builder.xml.dynamic.ForEachSqlNode;
- import org.apache.ibatis.executor.ErrorContext;
- import org.apache.ibatis.executor.Executor;
- import org.apache.ibatis.executor.ExecutorException;
- import org.apache.ibatis.logging.Log;
- import org.apache.ibatis.logging.LogFactory;
- import org.apache.ibatis.mapping.BoundSql;
- import org.apache.ibatis.mapping.MappedStatement;
- import org.apache.ibatis.mapping.ParameterMapping;
- import org.apache.ibatis.mapping.ParameterMode;
- import org.apache.ibatis.mapping.SqlSource;
- import org.apache.ibatis.mapping.MappedStatement.Builder;
- import org.apache.ibatis.plugin.Interceptor;
- import org.apache.ibatis.plugin.Intercepts;
- import org.apache.ibatis.plugin.Invocation;
- import org.apache.ibatis.plugin.Plugin;
- import org.apache.ibatis.plugin.Signature;
- import org.apache.ibatis.reflection.MetaObject;
- import org.apache.ibatis.reflection.property.PropertyTokenizer;
- import org.apache.ibatis.session.Configuration;
- import org.apache.ibatis.session.ResultHandler;
- import org.apache.ibatis.session.RowBounds;
- import org.apache.ibatis.type.TypeHandler;
- import org.apache.ibatis.type.TypeHandlerRegistry;
- import com.flydreamer.page.Dialect;
- import com.flydreamer.page.MySql5Dialect;
- import com.flydreamer.page.OracleDialect;
- import com.flydreamer.page.Page;
- import com.flydreamer.page.PageContext;
- import com.flydreamer.page.ReflectHelper;
- //只攔截select部分
- @Intercepts({@Signature(type=Executor.class,method="query",args={ MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class })})
- publicclass PaginationInterceptor implements Interceptor{
- privatefinalstatic Log log = LogFactory.getLog(PaginationInterceptor.class);
- Dialect dialect = new MySql5Dialect();
- public Object intercept(Invocation invocation) throws Throwable {
- MappedStatement mappedStatement=(MappedStatement)invocation.getArgs()[0];
- Object parameter = invocation.getArgs()[1];
- BoundSql boundSql = mappedStatement.getBoundSql(parameter);
- String originalSql = boundSql.getSql().trim();
- RowBounds rowBounds = (RowBounds)invocation.getArgs()[2];
- Object parameterObject = boundSql.getParameterObject();
- if(boundSql==null || boundSql.getSql()==null || "".equals(boundSql.getSql()))
- returnnull;
- //分頁引數--上下文傳參
- Page page = null;
- PageContext context=PageContext.getContext();
- //map傳參每次都將currentPage重置,先判讀map再判斷context
- if(parameterObject!=null)
- page = (Page)ReflectHelper.isPage(parameterObject,"page");
- //分頁引數--context引數裡的Page傳參
- if(page==null && context.isPagination()==true)
- {
- page = context;
- }
- //後面用到了context的東東
- if(page!=null && page.isPagination()==true)
- {
- int totpage=page.getTotalRows();
- //得到總記錄數
- if (totpage==0)
- {
- StringBuffer countSql = new StringBuffer(originalSql.length()+100 );
- countSql.append("select count(1) from (").append(originalSql).append(") t");
- Connection connection=mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection() ;
- PreparedStatement countStmt = connection.prepareStatement(countSql.toString());
- BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(),countSql.toString(),boundSql.getParameterMappings(),parameterObject);
- setParameters(countStmt,mappedStatement,countBS,parameterObject);
- ResultSet rs = countStmt.executeQuery();
- if (rs.next()) {
- totpage = rs.getInt(1);
- }
- rs.close();
- countStmt.close();
- connection.close();
- }
- //分頁計算
- page.init(totpage,page.getPageSize(),page.getCurrentPage());
- if(rowBounds == null || rowBounds == RowBounds.DEFAULT){
- rowBounds= new RowBounds(page.getPageSize()*(page.getCurrentPage()-1),page.getPageSize());
- }
- //分頁查詢 本地化物件 修改資料庫注意修改實現
- String pagesql=dialect.getLimitString(originalSql, rowBounds.getOffset(), rowBounds.getLimit());
- invocation.getArgs()[2] = new RowBounds(RowBounds.NO_ROW_OFFSET, RowBounds.NO_ROW_LIMIT);
- BoundSql newBoundSql = new BoundSql(mappedStatement.getConfiguration(), pagesql,boundSql.getParameterMappings(),boundSql.getParameterObject());
- MappedStatement newMs = copyFromMappedStatement(mappedStatement,new BoundSqlSqlSource(newBoundSql));
- invocation.getArgs()[0]= newMs;
- }
- return invocation.proceed();
- }
- publicstaticclass BoundSqlSqlSource implements SqlSource {
- BoundSql boundSql;
- public BoundSqlSqlSource(BoundSql boundSql) {
- this.boundSql = boundSql;
- }
- public BoundSql getBoundSql(Object parameterObject) {
- return boundSql;
- }
- }
- public Object plugin(Object arg0) {
- return Plugin.wrap(arg0, this);
- }
- publicvoid setProperties(Properties arg0) {
- }
- /**
- * 對SQL引數(?)設值,參考org.apache.ibatis.executor.parameter.DefaultParameterHandler
- * @param ps
- * @param mappedStatement
- * @param boundSql
- * @param parameterObject
- * @throws SQLException
- */
- privatevoid setParameters(PreparedStatement ps,MappedStatement mappedStatement,BoundSql boundSql,Object parameterObject) throws SQLException {
- ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
- List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
- if (parameterMappings != null) {
- Configuration configuration = mappedStatement.getConfiguration();
- TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
- MetaObject metaObject = parameterObject == null ? null: configuration.newMetaObject(parameterObject);
- for (int i = 0; i < parameterMappings.size(); i++) {
- ParameterMapping parameterMapping = parameterMappings.get(i);
- if (parameterMapping.getMode() != ParameterMode.OUT) {
- Object value;
- String propertyName = parameterMapping.getProperty();
- PropertyTokenizer prop = new PropertyTokenizer(propertyName);
- if (parameterObject == null) {
- value = null;
- } elseif (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
- value = parameterObject;
- } elseif (boundSql.hasAdditionalParameter(propertyName)) {
- value = boundSql.getAdditionalParameter(propertyName);
- } elseif (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX)&& boundSql.hasAdditionalParameter(prop.getName())) {
- value = boundSql.getAdditionalParameter(prop.getName());
- if (value != null) {
- value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));
- }
- } else {
- value = metaObject == null ? null : metaObject.getValue(propertyName);
- }
- TypeHandler typeHandler = parameterMapping.getTypeHandler();
- if (typeHandler == null) {
- thrownew ExecutorException("There was no TypeHandler found for parameter "+ propertyName + " of statement "+ mappedStatement.getId());
- }
- typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
- }
- }
- }
- }
- private MappedStatement copyFromMappedStatement(MappedStatement ms,
- SqlSource newSqlSource) {
- Builder builder = new MappedStatement.Builder(ms.getConfiguration(),
- ms.getId(), newSqlSource, ms.getSqlCommandType());
- builder.resource(ms.getResource());
- builder.fetchSize(ms.getFetchSize());
- builder.statementType(ms.getStatementType());
- builder.keyGenerator(ms.getKeyGenerator());
- builder.keyProperty(ms.getKeyProperty());
- builder.timeout(ms.getTimeout());
- builder.parameterMap(ms.getParameterMap());
- builder.resultMaps(ms.getResultMaps());
- builder.cache(ms.getCache());
- MappedStatement newMs = builder.build();
- return newMs;
- }
- }
簡要說明:剛剛忘記了,有一些查詢操作是不需要分頁的。可以自行修改攔截器中程式碼部分,加個判斷啥的。
5:spring 配置
[html] view plaincopy
- <beanid="paginationInterceptor"class="com.flydreamer.interceptor.PaginationInterceptor"></bean>
[html] view plaincopy
- <beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">
- <propertyname="dataSource"ref="dataSource"/>
- <propertyname="plugins">
- <refbean="paginationInterceptor"/>
- </property>
- </bean>