中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

JdbcTemplate簡易封裝

2018-07-20    來源:open-open

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用
在本篇博文中,我們將對SpringJDBC提供的JdbcTemplate進(jìn)行簡易封裝,使其更加的易用,更加貼近上篇博文中對于SQL管理的設(shè)計。

我們希望在使用將要封裝的這個工具進(jìn)行數(shù)據(jù)庫操作時有以下幾個優(yōu)勢:

  • 不處理數(shù)據(jù)獲取異常

  • 不關(guān)心日志記錄

  • 即可以使用我們XML文件中的SQL語句,也可以使用在業(yè)務(wù)方法中定義的SQL語句。(因為我們設(shè)計的XML文件并不能夠非常友好的支持條件查詢,所以對于需要條件查詢的情況,我們需要在業(yè)務(wù)方法中編寫查詢SQL)

對于第一個優(yōu)勢而言,我們需要替換在JdbcTemplate中使用的 org.springframework.jdbc.core.RowMapper<T>接口。這個接口提供了一個T mapRow(ResultSet rs, int rowNum) throws SQLException方法,這個方法用于從查詢出的結(jié)果集(ResultSet)中依次取出每行每列的數(shù)據(jù)。我們之所以要替換這個接口,主要是為了處 理這個方法中ResultSet形參獲取列值時的一個缺陷,當(dāng)我們獲取一個并不存在的列的值時會拋出SQLException。所以我們的目標(biāo)是,如果我 們嘗試獲取一個不存在的列的值時不拋出錯誤,而是返回一個默認(rèn)值。

為了達(dá)到這個目標(biāo),我們給出一個設(shè)計方案:當(dāng)每次查詢返回ResultSet后,我們將這個ResultSet中的列名放入一個Map,以列名作為鍵,值可以是任意值。當(dāng)我們執(zhí)行g(shù)etString(String columnLabel)、getDouble(String columnLabel)等這些取值方法時,我們先把傳入的列名(columnLabel)拿到Map中查詢是否存在,如果存在再調(diào)用ResultSet原生的getString(String columnLabel)、getDouble(String columnLabel)等這些方法進(jìn)行取值,反之返回一個默認(rèn)值,通常我們可以設(shè)置為null。源碼如下:

package com.kiiwow.framework.database.jdbc;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.jdbc.core.simple.ParameterizedRowMapper;

/**
 * 
 * RowMapper
 * @author leon.gan
 * @param <T>
 */
public abstract class RowMapper<T> implements ParameterizedRowMapper<T> {
    
    private Map<String, Integer> columnIndexes;

    /**
     * 每次實際取值之前先判斷列名是否在結(jié)果集中存在
     */
    protected int findColumn(ResultSet resultSet, String columnName) throws SQLException {
        if (columnIndexes == null) {
            buildIndexes(resultSet);
        }
        Integer index = columnIndexes.get(columnName);
        if (index == null) return -1;
        return index;
    }

    /**
     * 將結(jié)果集中的列名和一個迭代數(shù)字放入map中映射
     */
    private void buildIndexes(ResultSet resultSet) throws SQLException {
        columnIndexes = new HashMap<String, Integer>();
        ResultSetMetaData meta = resultSet.getMetaData();
        int count = meta.getColumnCount();
        for (int i = 1; i < count + 1; i++) {
            String column = meta.getColumnName(i);
            columnIndexes.put(column.toLowerCase(), i);
        }
    }

    protected String getString(ResultSet resultSet, String column) throws SQLException {
        return getString(resultSet, column, null);
    }

    protected String getString(ResultSet resultSet, String column, String defaultValue) throws SQLException {
        int columnIndex = findColumn(resultSet, column);
        if (columnIndex > 0) return resultSet.getString(columnIndex);
        return defaultValue;
    }

    protected Date getDate(ResultSet resultSet, String column) throws SQLException {
        return getDate(resultSet, column, null);
    }

    protected Date getDate(ResultSet resultSet, String column, Date defaultValue) throws SQLException {
        int columnIndex = findColumn(resultSet, column);
        if (columnIndex > 0) return resultSet.getTimestamp(columnIndex);
        return defaultValue;
    }

    protected int getInt(ResultSet resultSet, String column) throws SQLException {
        return getInt(resultSet, column, 0);
    }

    protected int getInt(ResultSet resultSet, String column, int defaultValue) throws SQLException {
        int columnIndex = findColumn(resultSet, column);
        if (columnIndex > 0) return resultSet.getInt(columnIndex);
        return defaultValue;
    }

    protected double getDouble(ResultSet resultSet, String column) throws SQLException {
        return getDouble(resultSet, column, 0);
    }

    protected double getDouble(ResultSet resultSet, String column, double defaultValue) throws SQLException {
        int columnIndex = findColumn(resultSet, column);
        if (columnIndex > 0) return resultSet.getDouble(columnIndex);
        return defaultValue;
    }

    public abstract T mapRow(ResultSet resultSet, int rowNum) throws SQLException;
}


對于第二個優(yōu)勢而言,我們需要對JdbcTemplate的方法執(zhí)行進(jìn)行日志記錄,同時替換其原生的RowMapper接口。我們順便調(diào)整了其原生形參的順序,以使代碼看起來更易讀(僅個人喜好)。源碼如下:

package com.kiiwow.framework.database.jdbc;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

import com.kiiwow.framework.log.LogNameConstants;
import com.kiiwow.framework.util.StopWatch;

/**
 * 
 * JDBCAccess
 *
 * JDBC執(zhí)行工具類,僅對原生方法添加了日志記錄,并調(diào)整了形參列表的順序,同時使用自定義的RowMapper來替換原生RowMapper
 * 
 * @author leon.gan
 */
public class JDBCAccess {

    private final Logger logger = LoggerFactory.getLogger(LogNameConstants.SQL_LOGGER);
    
    private JdbcTemplate jdbcTemplate;

    public <T> List<T> find(String sql, RowMapper<T> rowMapper, Object... params) {
        StopWatch watch = new StopWatch();
        try {
            return jdbcTemplate.query(sql, params, rowMapper);
        } finally {
            logger.debug("find, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});
        }
    }

    public <T> T findUniqueResult(String sql, RowMapper<T> rowMapper, Object... params) {
        StopWatch watch = new StopWatch();
        try {
            return jdbcTemplate.queryForObject(sql, params, rowMapper);
        } finally {
            logger.debug("findUniqueResult, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});
        }
    }

    public int findInteger(String sql, Object... params) {
        StopWatch watch = new StopWatch();
        try {
            return jdbcTemplate.queryForInt(sql, params);
        } finally {
            logger.debug("findInteger, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});
        }
    }

    public String findString(String sql, Object... params) {
        StopWatch watch = new StopWatch();
        try {
            return jdbcTemplate.queryForObject(sql, params, new RowMapper<String>() {
                @Override
                public String mapRow(ResultSet resultSet, int rowNum) throws SQLException {
                    return resultSet.getString(1);
                }
            });
        } finally {
            logger.debug("findString, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});
        }
    }

    public int insert(String sql, Object... params) {
        StopWatch watch = new StopWatch();
        try {
            return jdbcTemplate.update(sql, params);
        } finally {
            logger.debug("insert, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});
        }
    }
    
    public int update(String sql, Object... params) {
        StopWatch watch = new StopWatch();
        try {
            return jdbcTemplate.update(sql, params);
        } finally {
            logger.debug("update, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});
        }
    }
    
    public int delete(String sql, Object... params) {
        StopWatch watch = new StopWatch();
        try {
            return jdbcTemplate.update(sql, params);
        } finally {
            logger.debug("delete, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});
        }
    }

    public int[] batchExecute(String sql, List<Object[]> params) {
        StopWatch watch = new StopWatch();
        try {
            return jdbcTemplate.batchUpdate(sql, params);
        } finally {
            logger.debug("batchExecute, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});
        }
    }

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
   
}



對于第三個優(yōu)勢而言,我們只需要為上面封裝的JDBCAcess類中的每個方法提供兩種傳參方式即可,使其既支持XML文件中的SQL,也支持業(yè)務(wù)方法中定義的SQL。對于XML文件中定義的SQL,我們使用上一篇博文中設(shè)計的SqlMappingAnalyzer類進(jìn)行解析獲取具體SQL即可。源碼如下(字?jǐn)?shù)限制,已去掉注釋,但代碼很好懂):

package com.kiiwow.framework.database.jdbc;

import java.util.List;

import com.kiiwow.framework.platform.sqlmapping.SqlMappingAnalyzer;

/**
 * 對JDBCAccess的封裝,對每一個操作分別提供兩種形式:
 * 1) 自定義SQL模式,比如在條件查詢時,在SQL映射文件中是無法提供動態(tài)查詢SQL的,這個時候就采用自行編寫
 * 2) 指定映射SQL模式,通過指定了SQL別名從SQL映射文件中找到指定的SQL
 *
 * @author leon.gan
 *
 */
public final class JDBCAccessContext {

    private JDBCAccess jdbcAccess;
    
    public <T> List<T> findWithOutSqlMapping(String sql, RowMapper<T> rowMapper, Object... params) {
        return jdbcAccess.find(sql, rowMapper, params);
    }
    
    public <T> List<T> find(String alias, RowMapper<T> rowMapper, Object... params) {
        String sql = SqlMappingAnalyzer.getSpecificSql(alias);
        return jdbcAccess.find(sql, rowMapper, params);
    }
    
    public <T> T findUniqueResultWithOutSqlMapping(String sql, RowMapper<T> rowMapper, Object... params) {
        return jdbcAccess.findUniqueResult(sql, rowMapper, params);
    }

    public <T> T findUniqueResult(String alias, RowMapper<T> rowMapper, Object... params) {
        String sql = SqlMappingAnalyzer.getSpecificSql(alias);
        return jdbcAccess.findUniqueResult(sql, rowMapper, params);
    }

    public int findIntegerWithOutSqlMapping(String sql, Object... params) {
        return jdbcAccess.findInteger(sql, params);
    }

    public int findInteger(String alias, Object... params) {
        String sql = SqlMappingAnalyzer.getSpecificSql(alias);
        return jdbcAccess.findInteger(sql, params);
    }

    public String findStringWithOutSqlMapping(String sql, Object... params) {
        return jdbcAccess.findString(sql, params);
    }

    public String findString(String alias, Object... params) {
        String sql = SqlMappingAnalyzer.getSpecificSql(alias);
        return jdbcAccess.findString(sql, params);
    }
    
    public int insertWithOutSqlMapping(String sql, Object... params) {
        return jdbcAccess.insert(sql, params);
    }

    public int insert(String alias, Object... params) {
        String sql = SqlMappingAnalyzer.getSpecificSql(alias);
        return jdbcAccess.insert(sql, params);
    }

    public int updateWithOutSqlMapping(String sql, Object... params) {
        return jdbcAccess.update(sql, params);
    }

    public int update(String alias, Object... params) {
        String sql = SqlMappingAnalyzer.getSpecificSql(alias);
        return jdbcAccess.update(sql, params);
    }

    public int deleteWithOutSqlMapping(String sql, Object... params) {
        return jdbcAccess.delete(sql, params);
    }
    
    public int delete(String alias, Object... params) {
        String sql = SqlMappingAnalyzer.getSpecificSql(alias);
        return jdbcAccess.delete(sql, params);
    }
    
    public int[] batchExecuteWithOutSqlMapping(String sql, List<Object[]> params) {
        return jdbcAccess.batchExecute(sql, params);
    }
    
    public int[] batchExecute(String alias, List<Object[]> params) {
        String sql = SqlMappingAnalyzer.getSpecificSql(alias);
        return jdbcAccess.batchExecute(sql, params);
    }

    public void setJdbcAccess(JDBCAccess jdbcAccess) {
        this.jdbcAccess = jdbcAccess;
    }

    public JDBCAccess getJdbcAccess() {
        return jdbcAccess;
    }
    
}



至此,我們對于JdbcTemplate的封裝就完成了,我們只需要簡單調(diào)用最終的JDBCAccessContext類中的方法就可以優(yōu)雅的進(jìn)行數(shù)據(jù)庫操作。這個設(shè)計方案中還存在一些缺陷,比如每次取值時的列名過濾會影響性能等,前路漫漫,砥礪前行。

來自:http://my.oschina.net/devleon/blog/529083

標(biāo)簽: 代碼 數(shù)據(jù)庫

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇: JS 實現(xiàn) 使用堆實現(xiàn)Top K 算法

下一篇:JS 實現(xiàn)快速冪算法