1. 程式人生 > >springMVC+spring+mybatis 框架下分頁查詢

springMVC+spring+mybatis 框架下分頁查詢

一、Mapper.xml(xml)
 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sojson.common.dao.XXMapper" >
  <resultMap id="BaseResultMap" type="com.sojson.common.model.XX" >
    <result column="url" property="url" jdbcType="VARCHAR" />
    <result column="title"  property="title"  jdbcType="VARCHAR" />
    <result column="time"  property="time"  jdbcType="VARCHAR" />
    <result column="picture_address" property="picture_address" jdbcType="VARCHAR" />
  </resultMap>
  <sql id="Base_Column_List" >
    url,title,time,picture_address
  </sql>
  
  <sql id="limit_sql">
       <if test="page_sql != null and page_sql != ''">
        ${page_sql}
      </if>
  </sql>
 
 <sql id="where_all">
  	<where>
 
      	<if test="findContent != null and findContent !='' " >
      		distinguish_type = 0 
          	and (
        	LOWER(欄位1) like  LOWER(CONCAT("%",#{findContent,jdbcType=VARCHAR},"%")) or
        	LOWER(欄位2) like  LOWER(CONCAT("%",#{findContent,jdbcType=VARCHAR},"%")) 
        	)
		</if>

     </where>
  </sql>
 
  <select id="findCount" resultMap="BaseResultMap" >
 	 select count(url) from  zp
  </select>  
  
  <select id="findAll" resultMap="BaseResultMap"  >
    select 
    <include refid="Base_Column_List" />
    from zp
    <include  refid="limit_sql" />
  </select>
  
</mapper>
二、Mapper.java(dao)
package com.sojson.common.dao;

public interface XXMapper {}

三、BaseMybatisDao.java
  package com.sojson.core.mybatis;

import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import com.sojson.common.utils.LoggerUtils;
import com.sojson.common.utils.StringUtils;
import com.sojson.core.mybatis.page.MysqlDialect;
import com.sojson.core.mybatis.page.Pagination;

@SuppressWarnings( { "unchecked" })
public class BaseMybatisDao<T> extends SqlSessionDaoSupport {

    private String NAMESPACE;
    final static  Class<? extends Object> SELF = BaseMybatisDao.class;
    protected final Log logger = LogFactory.getLog(BaseMybatisDao.class);
    /**預設的查詢Sql id*/
    final static String DEFAULT_SQL_ID = "findAll";
    /**預設的查詢Count sql id**/
    final static String DEFAULT_COUNT_SQL_ID = "findCount";
    public BaseMybatisDao() {
        try {
            Object genericClz = getClass().getGenericSuperclass();
            if (genericClz instanceof ParameterizedType) {
                Class<T> entityClass = (Class<T>) ((ParameterizedType) genericClz)
                        .getActualTypeArguments()[0];
                NAMESPACE = entityClass.getPackage().getName() + "."
                        + entityClass.getSimpleName();
            }
        } catch (RuntimeException e) {
            LoggerUtils.error(SELF, "初始化失敗,繼承BaseMybatisDao,沒有泛型!");
        }
    }
    

    /**
     * 分頁
     *
     * @param sqlId
     *            主語句
     * @param countId
     *            Count 語句
     * @param params
     *            引數
     * @param pageNo
     *            第幾頁
     * @param pageSize每頁顯示多少條
     * @param requiredType	返回的型別[可以不傳參]
     * @return
     */
    public Pagination findPage(String sqlId, String countId, Map<String, Object> params, Integer pageNo,
            Integer pageSize) {
        pageNo = null == pageNo ? 1 : pageNo;
        pageSize = null == pageSize ? 10 : pageSize;
        Pagination page = new Pagination();
        page.setPageNo(pageNo);
        page.setPageSize(pageSize);
        Configuration c = this.getSqlSession().getConfiguration();
        int offset = (page.getPageNo() - 1) * page.getPageSize();
        String page_sql = String.format(" limit  %s , %s ", offset,pageSize);
        params.put("page_sql", page_sql);

        sqlId =  String.format("%s.%s", NAMESPACE,sqlId) ;

        BoundSql boundSql = c.getMappedStatement(sqlId).getBoundSql(params);
        String sqlcode = boundSql.getSql();
        LoggerUtils.fmtDebug(SELF, "findPage sql : %s",sqlcode );
        String countCode = "";
        BoundSql countSql = null;
        if (StringUtils.isBlank(countId)) {
            countCode = sqlcode;
            countSql = boundSql;
        } else {
            countId = String.format("%s.%s", NAMESPACE,countId) ;
            countSql = c.getMappedStatement(countId).getBoundSql(params);
            countCode = countSql.getSql();
        }
        try {
            Connection conn = this.getSqlSession().getConnection();

            List resultList = this.getSqlSession().selectList(sqlId, params);

            page.setList(resultList);

            /**
             * 處理Count
             */
            PreparedStatement ps = getPreparedStatement4Count(countCode, countSql
                    .getParameterMappings(), params, conn);
            ps.execute();
            ResultSet set = ps.getResultSet();

            while (set.next()) {
                page.setTotalCount(set.getInt(1));
            }
        } catch (Exception e) {
            LoggerUtils.error(SELF, "jdbc.error.code.findByPageBySqlId",e);
        }
        return page;

    }
    /**
     * 過載減少引數DEFAULT_SQL_ID, "findCount"
     *
     * @param params
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Pagination findPage(Map<String, Object> params, Integer pageNo, Integer pageSize) {
        return findPage(DEFAULT_SQL_ID, DEFAULT_COUNT_SQL_ID, params, pageNo, pageSize);
    }
    /**
     * 組裝
     * @param sql
     * @param parameterMappingList
     * @param params
     * @param conn
     * @return
     * @throws SQLException
     */
    private PreparedStatement getPreparedStatement(String sql,
            List<ParameterMapping> parameterMappingList,
            Map<String, Object> params, Connection conn) throws SQLException {
        /**
         * 分頁根據資料庫分頁
         */
        MysqlDialect o = new MysqlDialect();

        PreparedStatement ps = conn.prepareStatement(o.getCountSqlString(sql));
        int index = 1;
        for (int i = 0; i < parameterMappingList.size(); i++) {
            ps.setObject(index++, params.get(parameterMappingList.get(i)
                    .getProperty()));
        }
        return ps;
    }
    /**
     * 分頁查詢Count 直接用使用者自己寫的Count sql
     * @param sql
     * @param parameterMappingList
     * @param params
     * @param conn
     * @return
     * @throws SQLException
     */
    private PreparedStatement getPreparedStatement4Count(String sql,
            List<ParameterMapping> parameterMappingList,
            Map<String, Object> params, Connection conn) throws SQLException {
        PreparedStatement ps = conn.prepareStatement(StringUtils.trim(sql));
        int index = 1;
        for (int i = 0; i < parameterMappingList.size(); i++) {
            ps.setObject(index++, params.get(parameterMappingList.get(i)
                    .getProperty()));
        }
        return ps;
    }


}

四、分頁實體實體
  1、Dialect
   package com.sojson.core.mybatis.page;

   public interface Dialect {
	
	public static final String RS_COLUMN = "totalCount";
    
    public boolean supportsLimit();

    /**
     * 以傳入SQL為基礎組裝分頁查詢的SQL語句,傳遞給myBatis呼叫
     * @param sql 原始SQL
     * @param offset 分頁查詢的記錄的偏移量
     * @param limit 每頁限定記錄數
     * @return 拼裝好的SQL
     */
    public String getLimitSqlString(String sql, int offset, int limit);
    
    /**
     * 以傳入SQL為基礎組裝總記錄數查詢的SQL語句
     * @param sql 原始SQL
     * @return 拼裝好的SQL
     */
    public String getCountSqlString(String sql);
}
 2、MysqlDialect
package com.sojson.core.mybatis.page;

public class MysqlDialect implements Dialect {
	protected static final String SQL_END_DELIMITER = ";";
	
	public String getLimitSqlString(String sql, int offset, int limit) {		
		sql = sql.trim();
		boolean isForUpdate = false;
		if ( sql.toLowerCase().endsWith(" for update") ) {
			sql = sql.substring( 0, sql.length()- 11 );
			isForUpdate = true;
		}
		
		if(offset < 0){
		    offset = 0;
		}
		
		StringBuffer pagingSelect = new StringBuffer();

		pagingSelect.append(sql +" limit "+offset+"," +limit);
		

		if ( isForUpdate ) {
			pagingSelect.append( " for update" );
		}
		
		return pagingSelect.toString();
	}

	public String getCountSqlString(String sql) {
		sql = trim(sql);
		StringBuffer sb = new StringBuffer(sql.length() + 10);
		sb.append("SELECT COUNT(1) AS " + RS_COLUMN + " FROM  ( ");
		sb.append(sql);
		sb.append(")a");
		return sb.toString();
	}

	public boolean supportsLimit() {
		return true;
	}

	private static String trim(String sql) {
		sql = sql.trim();
		if (sql.endsWith(SQL_END_DELIMITER)) {
			sql = sql.substring(0, sql.length() - 1
					- SQL_END_DELIMITER.length());
		}
		return sql;
	}
}
 3、Paginable
 package com.sojson.core.mybatis.page;

/**
 * 
 * 開發公司:SOJSON線上工具 <p>
 * 版權所有:© www.sojson.com<p>
 * 部落格地址:http://www.sojson.com/blog/  <p>
 * <p>
 * 
 * 分頁實體
 * 
 * <p>
 * 
 * 區分 責任人 日期    說明<br/>
 * 建立 周柏成 2016年6月2日  <br/>
 *
 * @author zhou-baicheng
 * @email  
[email protected]
* @version 1.0,2016年6月2日 <br/> * */ public interface Paginable { /** * 總記錄數 * * @return */ public int getTotalCount(); /** * 總頁數 * * @return */ public int getTotalPage(); /** * 每頁記錄數 * * @return */ public int getPageSize(); /** * 當前頁號 * * @return */ public int getPageNo(); /** * 是否第一頁 * * @return */ public boolean isFirstPage(); /** * 是否最後一頁 * * @return */ public boolean isLastPage(); /** * 返回下頁的頁號 */ public int getNextPage(); /** * 返回上頁的頁號 */ public int getPrePage(); } 4、SimplePage package com.sojson.core.mybatis.page; public class SimplePage implements Paginable { private static final long serialVersionUID = 1L; public static final int DEF_COUNT = 20; public SimplePage() { } public SimplePage(int pageNo, int pageSize, int totalCount) { if (totalCount <= 0) { this.totalCount = 0; } else { this.totalCount = totalCount; } if (pageSize <= 0) { this.pageSize = DEF_COUNT; } else { this.pageSize = pageSize; } if (pageNo <= 0) { this.pageNo = 1; } else { this.pageNo = pageNo; } if ((this.pageNo - 1) * this.pageSize >= totalCount) { this.pageNo = totalCount / pageSize; if(this.pageNo==0){ this.pageNo = 1 ; } } } /** * 調整分頁引數,使合理化 */ public void adjustPage() { if (totalCount <= 0) { totalCount = 0; } if (pageSize <= 0) { pageSize = DEF_COUNT; } if (pageNo <= 0) { pageNo = 1; } if ((pageNo - 1) * pageSize >= totalCount) { pageNo = totalCount / pageSize; } } public int getPageNo() { return pageNo; } public int getPageSize() { return pageSize; } public int getTotalCount() { return totalCount; } public int getTotalPage() { int totalPage = totalCount / pageSize; if (totalCount % pageSize != 0 || totalPage == 0) { totalPage++; } return totalPage; } public boolean isFirstPage() { return pageNo <= 1; } public boolean isLastPage() { return pageNo >= getTotalPage(); } public int getNextPage() { if (isLastPage()) { return pageNo; } else { return pageNo + 1; } } public int getPrePage() { if (isFirstPage()) { return pageNo; } else { return pageNo - 1; } } protected int totalCount = 0; protected int pageSize = 20; protected int pageNo = 1; public void setTotalCount(int totalCount) { this.totalCount = totalCount; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public void setPageNo(int pageNo) { this.pageNo = pageNo; } protected int filterNo; public int getFilterNo() { return filterNo; } public void setFilterNo(int filterNo) { this.filterNo = filterNo; } } 5、Pagination package com.sojson.core.mybatis.page; import java.util.List; /** * * 開發公司:SOJSON線上工具 <p> * 版權所有:© www.sojson.com<p> * 部落格地址:http://www.sojson.com/blog/ <p> * <p> * * 分頁的物件,以及分頁頁碼輸出 * * <p> * * 區分 責任人 日期    說明<br/> * 建立 周柏成 2016年6月2日  <br/> * * @author zhou-baicheng * @email
[email protected]
* @version 1.0,2016年6月2日 <br/> * */ @SuppressWarnings("serial") public class Pagination<T> extends SimplePage implements java.io.Serializable,Paginable { public Pagination() { } public Pagination(int pageNo, int pageSize, int totalCount) { super(pageNo, pageSize, totalCount); } @SuppressWarnings("unchecked") public Pagination(int pageNo, int pageSize, int totalCount, List list) { super(pageNo, pageSize, totalCount); this.list = list; } public int getFirstResult() { return (pageNo - 1) * pageSize; } /** * 當前頁的資料 */ private List<T> list; public List<T> getList() { return list; } public void setList(List<T> list) { this.list = list; } /**SOJSON SEO 翻頁版本*/ public String getWebPage(String page){ StringBuffer pageHtml = new StringBuffer("<ul class='pagination'>"); if(this.getPageNo()>1){ if(this.getPageNo()>5){ pageHtml.append("<li class='prev'><a href='javascript:;' onclick='" + page + "'>首頁</a></li>"); } pageHtml.append("<li class='prev'><a href='" + page + "" + (this.getPageNo() - 1) + "'>上一頁</a></li>"); } for (int i = this.getPageNo()-2<=0?1:this.getPageNo()-2,no = 1; i <= this.getTotalPage()&& no <6 ; i++,no++) { if (this.getPageNo() == i) { pageHtml.append("<li class='active'><a href='javascript:void(0);' >" + i + "</a></li>"); }else{ pageHtml.append("<li><a href='" + page + "" + i + "'>" + i + "</a></li>"); } } if(this.getPageNo() < this.getTotalPage()){ pageHtml.append("<li class='next'><a href='" + page + "" + (this.getPageNo() + 1) + "'>下一頁</a></li>"); } pageHtml.append("</ul>"); return pageHtml.toString(); } /**Ajxa翻頁*/ public String getSiAjaxPageHtml(){ StringBuffer pageHtml = new StringBuffer("<ul class='pagination'>"); if(this.getPageNo()>1){ if(this.getPageNo()>5){ pageHtml.append("<li class='prev'><a href='javascript:;' onclick='goPageByAjax(1)'>首頁</a></li>"); } pageHtml.append("<li class='prevd'><a href='javascript:;' onclick='goPageByAjax(" + (this.getPageNo() - 1) + ")'>上一頁</a></li>"); } for (int i = this.getPageNo()-2<=0?1:this.getPageNo()-2,no = 1; i <= this.getTotalPage()&& no <6 ; i++,no++) { if (this.getPageNo() == i) { pageHtml.append("<li class='active'><a href='javascript:void(0);' >" + i + "</a></li>"); }else{ pageHtml.append("<li><a href='javascript:;' onclick='goPageByAjax(" + i + ")'>" + i + "</a></li>"); } } if(this.getPageNo() < this.getTotalPage()){ pageHtml.append("<li class='next'><a href='javascript:;' onclick='goPageByAjax(" + (this.getPageNo() + 1) + ")'>下一頁</a></li>"); } pageHtml.append("</ul>"); return pageHtml.toString(); } /**普通翻頁*/ public String getPageHtml(){ StringBuffer pageHtml = new StringBuffer("<ul class='pagination'>"); if(this.getPageNo()>1){ if(this.getPageNo()>5){ pageHtml.append("<li class='prev'><a href='javascript:;' onclick='_submitform(1)'>首頁</a></li>"); } pageHtml.append("<li class='prev'><a href='javascript:;' onclick='_submitform(" + (this.getPageNo() - 1) + ")'>上一頁</a></li>"); } for (int i = this.getPageNo()-2<=0?1:this.getPageNo()-2,no = 1; i <= this.getTotalPage()&& no <6 ; i++,no++) { if (this.getPageNo() == i) { pageHtml.append("<li class='active'><a href='javascript:void(0);' >" + i + "</a></li>"); }else{ pageHtml.append("<li><a href='javascript:;' onclick='_submitform(" + i + ")'>" + i + "</a></li>"); } } if(this.getPageNo() < this.getTotalPage()){ pageHtml.append("<li class='next'><a href='javascript:;' onclick='_submitform(" + (this.getPageNo() + 1) + ")'>下一頁</a></li>"); } pageHtml.append("</ul>"); pageHtml.append("<script>"); pageHtml.append(" function _submitform(pageNo){"); pageHtml.append(" $(\"#formId\").append($(\"<input type='hidden' value='\" + pageNo +\"' name='pageNo'>\")).submit();"); pageHtml.append(" }"); pageHtml.append("</script>"); return pageHtml.toString(); } } 五、分頁的內容實體 model(根據具體業務來定XX.java) 六、Service.java(介面) package com.sojson.user.service; import java.util.Map; import com.sojson.common.model.XX; import com.sojson.core.mybatis.page.Pagination; public interface XXService { Pagination<XX> findByPage(Map<String, Object> params, Integer pageNo, Integer pageSize); } 七、ServiceImpl.java /** * * * @author Administrator 2017年3月20日 下午2:31:35 * @version 1.0 */ @Service public class XXServiceImpl extends BaseMybatisDao<XXMapper> implements XXService { /** * @param pageNo * @param pageSize * * @return * * @author Administrator Mar 21, 2017 10:09:09 AM * @version 1.0 */ @Override public Pagination<ZP> findByPage(Map<String, Object> resultMap, Integer pageNo, Integer pageSize) { return super.findPage(resultMap, pageNo, pageSize); } } 八、Controller @Controller @Scope(value="prototype") @RequestMapping("member") public class MemberController extends BaseController { /*** * 使用者手動操作Session * */ @Autowired XXService xxService; /** * 使用者列表管理 * @return */ @RequestMapping(value="list") public ModelAndView list(ModelMap map, Integer pageNo, String findContent, String findContentc) { map.put("findContent", findContent);//模糊查詢 Pagination<UUserAndExt> page = userService.findByPage(map, pageNo, pageSize); map.put("page", page); return new ModelAndView("member/list"); } }

九、jsp頁面/ftl頁面
            <div class="page-heading">
                <form method="get" action="" id="formId" class="form-inline">
                    <div class="wrapper">
                        <div class="directory-info-row">
                            <div class="row">
                                <#if page?exists && page.list?size gt 0> 
								  <#list page.list as it>
                                    <div class="col-md-4 col-sm-4">
                                       <div class="panel">
                                          <div class="panel-body">
                                            <h4>${it.title?default(' ')}</h4>
                                            <div class="media">
                                                <a class="pull-left" href="#"> <img class=""
                                                    style="width: 150px; height: 120px;"
                                                    src="${it.picture_address?default(' ')}" alt="">
                                                </a>
                                                <div class="media-body">
                                                    <address>
                                                        <strong> 更新時間: </strong> <br> <br> <abbr title="Phone">
                                                            ${it.time?default(' ')} </abbr>
                                                    </address>
                                                    <ul class="social-links">
                                                        <li><a title="" data-placement="top" data-toggle="tooltip"
                                                            class="tooltips" href=" ${it.url?default(' ')}"> <i
                                                                class="fa fa-video-camera"> </i>
                                                        </a></li>
                                                    </ul>
                                                </div>
                                            </div>
                                         </div>
                                      </div>
                                   </div>
                                </tr>
                              </#list>
							<#else> </#if> <input type="hidden" name="channel" value="zp">

                            </div>
                        </div>
                    </div>
                    <#if page?exists>
                    <div class="row" >
                        <div class="col-md-12 text-center" >
                            第${page.pageNo}頁/共${page.totalCount}條
                        </div>
                    </div>
                    <div class="row">
                            <div class="col-md-12 text-center clearfix">
                                ${page.pageHtml}
                            </div>
                    </div>
                    <div class="row" style="height: 50px;">
                            
                    </div>
                    </#if>
                </form>
         </div>