com.taobao.tddl.common.jdbc.MetaDataQueryForMapHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.taobao.tddl.common.jdbc.MetaDataQueryForMapHandler.java

Source

/*(C) 2007-2012 Alibaba Group Holding Limited.   
 *This program is free software; you can redistribute it and/or modify   
*it under the terms of the GNU General Public License version 2 as   
* published by the Free Software Foundation.   
* Authors:   
*   junyu <junyu@taobao.com> , shenxun <shenxun@taobao.com>,   
*   linxuan <linxuan@taobao.com> ,qihao <qihao@taobao.com>    
*/
package com.taobao.tddl.common.jdbc;

import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
//tddlspring
import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * select * sqlTypeselect columns 
 * 
 * @author linxuan
 *
 */
public class MetaDataQueryForMapHandler implements QueryForMapHandler {
    private static final Log log = LogFactory.getLog(MetaDataQueryForMapHandler.class);

    private ConcurrentHashMap<String/**/, TableMetaData/**/> tableMetaDatas = new ConcurrentHashMap<String, TableMetaData>();
    //ColumnMapRowMappertddlspring
    private ConcurrentHashMap<String/**/, ColumnMapRowMapper> rowMappers = new ConcurrentHashMap<String, ColumnMapRowMapper>();

    public MetaDataQueryForMapHandler() {

    }

    public Map<String, Object> queryForMap(JdbcTemplate jdbcTemplate, String tableName, String selectColumns,
            String whereSql, Object[] args) {
        tableName = tableName.toLowerCase();
        TableMetaData tmd = tableMetaDatas.get(tableName);
        StringBuilder sql = new StringBuilder("select ");
        if (tmd == null) {
            sql.append(selectColumns == null ? "*" : selectColumns);
        } else {
            sql.append(tmd.commaColumnNames);
        }
        //sql,sql
        //sql
        sql.append(" from ").append(tableName).append(" ").append(whereSql);

        if (log.isDebugEnabled()) {
            log.debug("sql=[" + sql.toString() + "], args=" + Arrays.asList(args));
        }

        try {
            return convert(jdbcTemplate.queryForObject(sql.toString(), args, getRowMapper(tableName)));
        } catch (EmptyResultDataAccessException e) {
            return null;
        } catch (DataAccessException e) {
            log.error("sql=[" + sql.toString() + "], args=" + Arrays.asList(args), e);
            throw e;
        }
    }

    public TableMetaData getTableMetaData(String tableName) {
        if (tableMetaDatas.get(tableName) == null) {
            throw new IllegalStateException(
                    "Must be called after queryForMap called at least once on table " + tableName);
        }
        return this.tableMetaDatas.get(tableName);
    }

    /**
     * @param tableName 
     */
    private ColumnMapRowMapper getRowMapper(String tableName) {
        ColumnMapRowMapper rowMapper = rowMappers.get(tableName);
        if (rowMapper == null) {
            rowMapper = new CachedColumnMapRowMapper(tableName);
            rowMappers.putIfAbsent(tableName, rowMapper);
            return rowMappers.get(tableName);
        }
        return rowMapper;
    }

    /**
     * 1.  ResultSetMetaData 
     * 2. Map(key)
     */
    private class CachedColumnMapRowMapper extends ColumnMapRowMapper {
        private final String tableName; //

        public CachedColumnMapRowMapper(String tableName) {
            this.tableName = tableName;
        }

        @Override
        public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
            TableMetaData tmd = tableMetaDatas.get(tableName);
            if (tmd == null) {
                //metaData 
                initMetaData(tableName, rs.getMetaData());
                tmd = tableMetaDatas.get(tableName);
                if (tmd == null) {
                    log.warn("MetaData is still null after initMetaData().");
                    return super.mapRow(rs, rowNum);
                }
            }
            //metadata metadatametadata
            Map mapOfColValues = super.createColumnMap(tmd.columns.length);
            for (int i = 1; i <= tmd.columns.length; i++) {
                String key = getColumnKey(tmd.columnNames[i - 1]);
                Object obj = getResultSetValue(tmd, rs, i);
                mapOfColValues.put(key, obj);
            }
            return mapOfColValues;
        }

        protected String getColumnKey(String columnName) {
            return columnName.toLowerCase();
        }

        /**
         * JdbcUtils.getResultSetValue(ResultSet rs, int index)Meta
         * @param indexthe column indexthe first column is 1, the second is 2, ... 
         */
        private Object getResultSetValue(TableMetaData tmd, ResultSet rs, int index) throws SQLException {
            Object obj = rs.getObject(index);
            if (obj instanceof Blob) {
                obj = rs.getBytes(index);
            } else if (obj instanceof Clob) {
                obj = rs.getString(index);
            } else if (obj != null && obj.getClass().getName().startsWith("oracle.sql.TIMESTAMP")) {
                obj = rs.getTimestamp(index);
            } else if (obj != null && obj.getClass().getName().startsWith("oracle.sql.DATE")) {
                String metaDataClassName = tmd.columns[index - 1].className;
                if ("java.sql.Timestamp".equals(metaDataClassName)
                        || "oracle.sql.TIMESTAMP".equals(metaDataClassName)) {
                    obj = rs.getTimestamp(index);
                } else {
                    obj = rs.getDate(index);
                }
            } else if (obj != null && obj instanceof java.sql.Date) {
                if ("java.sql.Timestamp".equals(tmd.columns[index - 1].className)) {
                    obj = rs.getTimestamp(index);
                }
            }
            return obj;
        }
    }

    /**
     * @param tableName 
     */
    private void initMetaData(String tableName, ResultSetMetaData rsmd) {
        try {
            int columnCount = rsmd.getColumnCount();
            String[] columnNames = new String[columnCount];
            ColumnMetaData[] columns = new ColumnMetaData[columnCount];
            for (int i = 1; i <= columnCount; i++) {
                columnNames[i - 1] = rsmd.getColumnName(i).toLowerCase();
                int sqlType = rsmd.getColumnType(i);
                if (sqlType == java.sql.Types.DATE) {
                    sqlType = java.sql.Types.TIMESTAMP;
                }
                int scale = rsmd.getScale(i);
                String className = rsmd.getColumnClassName(i);
                columns[i - 1] = new ColumnMetaData(sqlType, scale, className);
            }
            TableMetaData tmd = new TableMetaData(columnNames, columns);
            this.tableMetaDatas.putIfAbsent(tableName, tmd);
        } catch (SQLException e) {
            log.warn("Fetch Metadata from resultSet failed.", e);
        }
    }

    @SuppressWarnings("unchecked")
    private <T> T convert(Object obj) {
        return (T) obj;
    }

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