基於spring-jdbc的BaseDao(包含分頁)

網上找一下spring jdbc的分頁,基本都是一個類型,不知道爲啥,都是在Page對象中再進行查詢,這樣Page對象不就和數據庫操作混一起了嘛?看過其他的項目,有的是隻在Dao層查出個list(分頁結果集),其他的Page屬性在action中再封裝,我覺得每次都這樣,用着不方便,就自己再搞個輪子吧。下面開整。

1、先上Page對象吧

這裏有兩個構造方法,看需不需要總計錄數,如果不需要的話,後面查詢會少查一次,更方便,但是以防萬一,再給出一個有總記錄數的構造方法

package com.mos.base.sql;

import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

/**
 * Package Name: com.mos.base.sql
 * User: grq
 * Date: 2016/3/25
 * Time: 9:08
 * Description:some des here!
 */
public class Page<T> {

    //一頁顯示的記錄數
    private int numPerPage;
    //記錄總數
    private int totalRows;
    //總頁數
    private int totalPages;
    //當前頁碼
    private int currentPage;
    //起始行數
    private int startIndex;
    //結束行數
    private int lastIndex;
    //結果集存放List
    private List<T> resultList;

    public Page(int currentPage,int numPerPage,List<T> list){

        //設置每頁顯示記錄數
        setNumPerPage(numPerPage);
        //設置要顯示的頁數
        setCurrentPage(currentPage);
        //總記錄數
//        setTotalRows(list.isEmpty() ? 0 : list.size());
        //計算總頁數
        setTotalPages();
        //計算起始行數
        setStartIndex();
        //計算結束行數
        setLastIndex();
        System.out.println("lastIndex="+lastIndex);
        //裝入結果集
        setResultList(list);
    }
    public Page(int currentPage,int numPerPage,int totalRows,List<T> list){

        //設置每頁顯示記錄數
        setNumPerPage(numPerPage);
        //設置要顯示的頁數
        setCurrentPage(currentPage);
        //總記錄數
        setTotalRows(totalRows);
        //計算總頁數
        setTotalPages();
        //計算起始行數
        setStartIndex();
        //計算結束行數
        setLastIndex();
        System.out.println("lastIndex="+lastIndex);
        //裝入結果集
        setResultList(list);
    }

    public int getNumPerPage() {
        return numPerPage;
    }

    public void setNumPerPage(int numPerPage) {
        this.numPerPage = numPerPage;
    }

    public int getTotalRows() {
        return totalRows;
    }

    public void setTotalRows(int totalRows) {
        this.totalRows = totalRows;
    }

    public int getTotalPages() {
        return totalPages;
    }

    public void setTotalPages() {
        if(totalRows % numPerPage == 0){
            this.totalPages = totalRows / numPerPage;
        }else{
            this.totalPages = (totalRows / numPerPage) + 1;
        }
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public int getStartIndex() {
        return startIndex;
    }

    public void setStartIndex() {
        this.startIndex = (currentPage - 1) * numPerPage;
    }

    public int getLastIndex() {
        return lastIndex;
    }

    public void setLastIndex() {
        if( totalRows < numPerPage){
            this.lastIndex = totalRows;
        }else if((totalRows % numPerPage == 0) || (totalRows % numPerPage != 0 && currentPage < totalPages)){
            this.lastIndex = currentPage * numPerPage;
        }else if(totalRows % numPerPage != 0 && currentPage == totalPages){//最後一頁
            this.lastIndex = totalRows ;
        }
    }

    public List<T> getResultList() {
        return resultList;
    }

    public void setResultList(List<T> resultList) {
        this.resultList = resultList;
    }
}

2、SQLPageHandle

這個的作用是處理分頁的,比如mysql和oracle的不同,分別做一個實現就好了,細心的童鞋可能會發現上一篇的applicationContext.xml中注入了一個sQLPageHandle,其實就是這個,需要同時支持mysql和oracle的時候,用工廠注入就行了。

package com.mos.base.sql;

/**
 * 分頁處理接口
 * */
public interface SQLPageHandle {

    /**
     * 將傳入的SQL做分頁處理
     * 
     * @param String
     *            oldSql 原SQL
     * @param int pageNo 第幾頁,用來計算first 這個值由(pageNo-1)*pageSize
     * @param int pageSize 每頁數量
     * */
    public String handlerPagingSQL(String oldSql, int pageNo, int pageSize);

}

3、MysqlSQLPageHandleImpl

其實就是對sql進行重新拼接處理。

package com.mos.base.sql;

import org.apache.log4j.Logger;

/**
 * mysql數據庫的分頁實現
 * 
 * */
public class MysqlSQLPageHandleImpl implements SQLPageHandle {

    private Logger logger=Logger.getLogger(MysqlSQLPageHandleImpl.class);

    public String handlerPagingSQL(String oldSQL, int pageNo, int pageSize) {
        StringBuffer sql = new StringBuffer(oldSQL);
        if (pageSize > 0) {
            int firstResult = (pageNo - 1)*pageSize;
            if (firstResult <= 0) {
                sql.append(" limit ").append(pageSize);
            } else {
                sql.append(" limit ").append(firstResult).append(",")
                        .append(pageSize);
            }
        }
        return sql.toString();
    }

}

4、BaseDao

個人覺得這幾個最常用的就可以了,其他的可以再擴展,比如批量操作,我一直的想法就是先會走再會跑,單個的搞定了,批量的還遠嗎?

package com.mos.base.sql;


import java.util.List;
import java.util.Map;

/**
 * Package Name: com.mos.base
 * User: grq
 * Date: 2016/3/24
 * Time: 16:02
 * Description:some des here!
 */
public interface BaseDao {

    public <T> List<T> find(String sql, Object[] params, Class<T> tClass);

    public <T> int addOrUpdateOrDelete(String sql, Object[] params, Class<T> tClass);

    public <T> Page<T> queryPagination(String sql, Object[] parameters,int pageNo, int pageSize,  Class<T> entity);

    public <T> T findForObject(String sql, Object[] args, Class<T> classT);

    public Map<String,Object> find(String sql,Object[] params);

    public List<Map<String,Object>> queryList(String sql,Object[] params);
}

5、BaseDaoImpl

這個裏面好多坑。

  1. queryPagination(…….)方法中有個totalList,這個就是對應前面Page對象的totalRows,如果不需要,那就不用查詢了。
  2. 傳入參數提示Class< T>,我以爲比如User對象,傳入User.class就行了,然並卵,spring jdbc不支持自定義複雜對象,需要轉換,參考代碼。
  3. 查詢的時候如果沒有查詢條件,必須用沒條件的方法查詢,如果條件傳個null,sorry,等着catch exception吧。
package com.mos.base.sql;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * Package Name: com.mos.base
 * User: grq
 * Date: 2016/3/24
 * Time: 16:06
 * Description:some des here!
 */
@Repository
public class BaseDaoImpl implements BaseDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Resource
    protected SQLPageHandle sQLPageHandle;

    public <T> List<T> find(String sql, Object[] params, Class<T> tClass) {
        List<T> resultList = null;
        try {
            if (params != null && params.length > 0)
                resultList = jdbcTemplate.query(sql, params, new BeanPropertyRowMapper<T>(tClass));
            else
                // BeanPropertyRowMapper是自動映射實體類的
                resultList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<T>(tClass));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultList;
    }

    public <T> int addOrUpdateOrDelete(String sql, final Object[] params, Class<T> tClass) {
        int num = 0;
        try {
            if (params == null || params.length == 0)
                num = jdbcTemplate.update(sql);
            else
                num = jdbcTemplate.update(sql, new PreparedStatementSetter() {
                    public void setValues(PreparedStatement ps) throws SQLException {
                        for (int i = 0; i < params.length; i++)
                            ps.setObject(i + 1, params[i]);
                    }
                });
        } catch (Exception e) {
            e.printStackTrace();
            num = -1;
        }
        return num;

    }

    /**
     * @param sql
     * @param parameters
     * @param pageNo
     * @param pageSize
     * @param entity     jdbcTemplate.query由於需要返回自定義對象,調用此方法時候需要傳入new BeanPropertyRowMapper<T>(entity)
     * @param <T>
     * @return
     */
    public <T> Page<T> queryPagination(String sql, Object[] parameters, int pageNo, int pageSize, Class<T> entity) {
        // 將SQL語句進行分頁處理
        String newSql = sQLPageHandle.handlerPagingSQL(sql, pageNo, pageSize);
        List<T> list = null;
        List<T> totalList = null;
        if (parameters == null || parameters.length <= 0) {
            totalList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<T>(entity));
            list = jdbcTemplate.query(newSql, new BeanPropertyRowMapper<T>(entity));
        } else {
            totalList = jdbcTemplate.query(sql, parameters, new BeanPropertyRowMapper<T>(entity));
            list = jdbcTemplate.query(newSql, parameters, new BeanPropertyRowMapper<T>(entity));
        }
        // 根據參數的個數進行差別查詢
        Page<T> page = new Page<T>(pageNo, pageSize, totalList.isEmpty() ? 0 : totalList.size(), list);

        return page;
    }

    /**
     * @param sql
     * @param args
     * @param classT 注意該參數,jdbcTemplate.queryForObject傳入的不能是自定義的classType,
     *               如果是自定義的,需要經過new BeanPropertyRowMapper<T>(classT)轉換,默認支持的只有比如String,int等類型
     * @param <T>
     * @return
     */
    public <T> T findForObject(String sql, Object[] args, Class<T> classT) {
        if (sql == null || sql.length() <= 0) {
            return null;
        }
        if (args == null || args.length <= 0) {
            return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<T>(classT));
        }
        return jdbcTemplate.queryForObject(sql, args, new BeanPropertyRowMapper<T>(classT));
    }

    public Map<String, Object> find(String sql, Object[] params) {
        return jdbcTemplate.queryForMap(sql,params);
    }

    public List<Map<String, Object>> queryList(String sql, Object[] params) {
        return jdbcTemplate.queryForList(sql,params);
    }
}

附上項目地址:https://git.oschina.net/chemors/mosMVC.git

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章