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

JdbcTemplate簡(jiǎn)易封裝

2018-07-20    來(lái)源:open-open

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

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

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

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

  • 即可以使用我們XML文件中的SQL語(yǔ)句,也可以使用在業(yè)務(wù)方法中定義的SQL語(yǔ)句。(因?yàn)槲覀冊(cè)O(shè)計(jì)的XML文件并不能夠非常友好的支持條件查詢,所以對(duì)于需要條件查詢的情況,我們需要在業(yè)務(wù)方法中編寫(xiě)查詢SQL)

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

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

    /**
     * 每次實(shí)際取值之前先判斷列名是否在結(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é)果集中的列名和一個(gè)迭代數(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;
}


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

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í)行工具類(lèi),僅對(duì)原生方法添加了日志記錄,并調(diào)整了形參列表的順序,同時(shí)使用自定義的RowMapper來(lái)替換原生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;
    }
   
}



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

package com.kiiwow.framework.database.jdbc;

import java.util.List;

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

/**
 * 對(duì)JDBCAccess的封裝,對(duì)每一個(gè)操作分別提供兩種形式:
 * 1) 自定義SQL模式,比如在條件查詢時(shí),在SQL映射文件中是無(wú)法提供動(dòng)態(tài)查詢SQL的,這個(gè)時(shí)候就采用自行編寫(xiě)
 * 2) 指定映射SQL模式,通過(guò)指定了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;
    }
    
}



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

來(lái)自:http://my.oschina.net/devleon/blog/529083

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

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

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

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