JdbcTemplateDao

package com.hoss.core.dao;

import com.hoss.core.exception.HossSqlException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

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

public interface SqlQueryDao {

    <T> Page<T> queryPageByConditionModel(Class<T>  resultClass,Pageable pageable,String sql,Object conditionModel) throws HossSqlException;

    <T> Page<T> queryPage(Class<T> resultClass,Pageable pageable,String sql,Object ... params);

    <T> Page<Map<String,Object>> queryPageByConditionModel(Pageable pageable,String sql,Object conditionMode) throws HossSqlException;

    <T> Page<Map<String,Object>> queryPage(Pageable pageable,String sql,Object ... params);

    <T> List<T> queryListByConditionModel(Class<T>  resultClass,String sql,Object conditionModel) throws HossSqlException;

    <T> List<T> queryList(Class<T> resultClass,String sql,Object ... params);

    <T> List<Map<String,Object>> queryListByConditionModel(String sql,Object conditionModel) throws HossSqlException;

    <T> List<Map<String,Object>> queryList(String sql,Object ... params);

    <T> T queryOneByConditionModel(Class<T>  resultClass,String sql,Object conditionModel) throws HossSqlException;

    <T> T queryOne(Class<T>  resultClass,String sql,Object ... params);

    Map<String,Object> queryOneByConditionModel(String sql,Object conditionModel) throws HossSqlException;

    Map<String,Object> queryOne(String sql,Object ... params);

    Number queryNumberByConditionMode(String sql,String numberKey,Object conditionModel) throws HossSqlException;

    Number queryNumber(String sql,String numberKey,Object ... params);

    Number queryCountByConditionMode(String sql,Object conditionModel) throws HossSqlException;

    Number queryCount(String sql,Object ... params);

    Integer execute(String sql,Object ...params);

    Integer executeByConditionMode(String sql,Object conditionModel) throws HossSqlException;

}

 

 

 

 

package com.hoss.core.dao;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;

import com.hoss.core.util.StringUtil;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;


import com.hoss.core.model.Broker;


@Repository
public class SqlQueryDaoImpl implements SqlQueryDao {

	private static final String SQL_KEY="#SQL#";
	private static final String COUNT_KEY="RESULT_COUNT";
	private static final String QUERY_COUNT_SQL=" SELECT COUNT(1) AS "+COUNT_KEY+" FROM ( "+SQL_KEY+" ) QUEYR_COUNT";
	private static final String DEFAULT_WEHRE=" 1=1 ";
	private static final Pattern REGEX= Pattern.compile(":{1}\\w+",Pattern.CASE_INSENSITIVE);
	private static final Pattern PATTERN=Pattern.compile("\\{[^{]*\\}");

	@Autowired
	private DataSource dataSource;

	private JdbcTemplate jdbcTemplate;
	@PostConstruct
	public void init(){
		jdbcTemplate=new JdbcTemplate(dataSource);
	}


	@Override
	public <T> Page<T> queryPageByConditionModel(Class<T> resultClass, Pageable pageable, String sql, Object conditionModel){
		SqlAndParams sp=generateSqlAndParams(sql, conditionModel);
		return queryPage(resultClass, pageable, sp.getSql(),sp.getParams().toArray());
	}

	@Override
	public <T> Page<T> queryPage(Class<T> resultClass, Pageable pageable, String sql, Object... params) {
		String newSql=new String ( sql+ getSortSql(pageable.getSort()) );
		Long total=queryCount(newSql,params).longValue();
		List<T> data=queryList(resultClass, genPageSql(newSql,pageable), params);
		return new PageImpl<T>(data,pageable,total);
	}

	@Override
	public Page<Map<String, Object>> queryPageByConditionModel(Pageable pageable, String sql, Object conditionMode) throws HossSqlException {
		SqlAndParams sp=generateSqlAndParams(sql,conditionMode);
		return queryPage(pageable, sp.getSql(),sp.getParams().toArray());
	}



	@Override
	public Page<Map<String, Object>> queryPage(Pageable pageable, String sql, Object... params) {
		String newSql=new String ( sql+ getSortSql(pageable.getSort()) );
		Long total=queryCount(newSql,params).longValue();
		List<Map<String,Object>> data=queryList(genPageSql(newSql,pageable), params);
		return new PageImpl<Map<String,Object>>(data,pageable,total);
	}

	@Override
	public <T> List<T> queryListByConditionModel(Class<T> resultClass, String sql, Object conditionModel) throws HossSqlException {
		SqlAndParams sp=generateSqlAndParams(sql,conditionModel);
		return queryList(resultClass, sp.getSql(), sp.getParams().toArray());
	}


	@Override
	public <T> List<T> queryList(Class<T> resultClass, String sql, Object... params) {
		return jdbcTemplate.query(sql,rowMapper(resultClass), params );
	}

	@Override
	public List<Map<String, Object>> queryListByConditionModel(String sql, Object conditionModel) throws HossSqlException {
		SqlAndParams sp=generateSqlAndParams(sql,conditionModel);
		return queryList(sp.getSql(), sp.getParams().toArray());
	}

	@Override
	public List<Map<String, Object>> queryList(String sql, Object... params) {
		System.out.println(sql);
		return jdbcTemplate.queryForList(sql, params);
	}

	@Override
	public <T> T queryOneByConditionModel(Class<T> resultClass, String sql, Object conditionModel) throws HossSqlException {
		SqlAndParams sp=generateSqlAndParams(sql,conditionModel);
		return queryOne(resultClass,sp.getSql(),sp.getParams().toArray());
	}


	@Override
	public <T>T queryOne(Class<T> resultClass, String sql, Object... params) {
        List<T> result=queryList(resultClass, sql, params);
        if( result==null || result.isEmpty() )
            return null;
		return result.get(0);
	}

	@Override
	public Map<String, Object> queryOneByConditionModel(String sql, Object conditionModel) throws HossSqlException {
		SqlAndParams sp=generateSqlAndParams(sql,conditionModel);
		return queryOne(sp.getSql(),sp.getParams().toArray());
	}



	@Override
	public Map<String, Object> queryOne(String sql, Object... params) {
		return jdbcTemplate.queryForMap(sql, params);
	}

	@Override
	public Number queryNumberByConditionMode(String sql, String numberKey, Object conditionModel) throws HossSqlException {
		SqlAndParams sp=generateSqlAndParams(sql, conditionModel);
		return queryNumber(sp.getSql(),numberKey,sp.getParams().toArray());
	}


	@Override
	public Number queryNumber(String sql, String numberKey, Object... params) {
		Map<String,Object> map=jdbcTemplate.queryForMap(sql, params);
        if(map==null)
            return null;
		return (Number) map.get(numberKey);
	}

	@Override
	public Number queryCountByConditionMode(String sql, Object conditionModel) throws HossSqlException {
		SqlAndParams sp=generateSqlAndParams(sql,conditionModel);
		return queryCount(sp.getSql(),sp.getParams().toArray());
	}


	@Override
	public Number queryCount(String sql, Object... params) {
		String query_count=QUERY_COUNT_SQL.replace(SQL_KEY,sql);
		return queryNumber(query_count,COUNT_KEY,params);
	}

    @Override
    public Integer execute(String sql, Object... params) {
        return jdbcTemplate.update(sql,params);
    }

    @Override
    public Integer executeByConditionMode(String sql, Object conditionModel) throws HossSqlException {
        SqlAndParams sp=generateSqlAndParams(sql,conditionModel);
        return execute(sp.getSql(),sp.getParams().toArray());
    }

    public String genPageSql(String sql,Pageable pageable){
		 StringBuffer pageSql=new StringBuffer(sql).append(" ");
		 pageSql.append("limit ");
		 pageSql.append( pageable.getOffset()).append(",").append(pageable.getPageSize());
		 return pageSql.toString();
	}


	/**获取排序SQl
	 * @param sort
	 * @return
	 */
	private String getSortSql(Sort sort){
		if(sort == null)
			return "";
		Iterator<Sort.Order> iterator= sort.iterator();
		StringBuffer sb=new StringBuffer();
		while (iterator.hasNext()){
			Sort.Order order=iterator.next();
			sb.append(" ").append(order.getProperty()).append(" ").append(order.getDirection());
			if( iterator.hasNext() ){
				sb.append(",");
			}
		}
        if( sb.length()>0 )
            return sb.insert(0," ORDER BY ").toString();
		return sb.toString();
	}


	/**生成  预编译 SQL 与参数
	 * @param sql 原始SQL
	 * @param conditionModel 查询条件模型
	 * @return
	 * @throws HossSqlException
	 */
	private SqlAndParams generateSqlAndParams(String sql,Object conditionModel) throws HossSqlException {
		String newSql=cleanNullAttributes(sql,conditionModel);
		Matcher matcher= REGEX.matcher(newSql);
		StringBuffer sb=new StringBuffer();
		SqlAndParams result=new SqlAndParams();
		while(matcher.find()){
			String key=matcher.group();
			String pk=key.replaceFirst(":","");
			Object value=getProperty(conditionModel,pk);
			if(value==null)
				throw new HossSqlException("param "+key+" is null by SQL :"+sql);
			else{
				matcher.appendReplacement(sb, paramAdd(result.getParams(),value));
			}
		}
		matcher.appendTail(sb);
		result.setSql(sb.toString());
		return result;

	}

	/**清除条件模型中 为NULL 的查询条件
	 * @param sql
	 * @param conditionModel
	 * @return
	 */
	private String cleanNullAttributes(String sql,Object conditionModel){
		Matcher sqlMatcher=PATTERN.matcher(sql);
		StringBuffer sb = new StringBuffer();

		while(sqlMatcher.find()){
			StringBuffer temp=new StringBuffer(sqlMatcher.group());
			temp.deleteCharAt(temp.length()-1).deleteCharAt(0);
			Matcher conditionMatcher= REGEX.matcher(temp);

			while(conditionMatcher.find()){
				String mapKey=conditionMatcher.group().replaceFirst(":","");
				Object value=getProperty(conditionModel,mapKey);
				if( value == null || (value instanceof String && ((String)value).trim().length()==0) ){
					temp=new StringBuffer(DEFAULT_WEHRE);
					break;
				}
			}
			sqlMatcher.appendReplacement(sb,temp.toString());
		}
		sqlMatcher.appendTail(sb);
		return sb.toString();
	}


	/**生成 SQL 查询所用到的参数 并生成相应的 预编译所用到的? (主要解决数组和集合参数 转化 SQL in 的问题)
	 * @param params
	 * @param value
	 * @return
	 */
	private String paramAdd(List<Object> params,Object value){
		int length=0;
		if( value instanceof  Collection ){
			Collection<?> collection=(Collection<?>)value;
			length=collection.size();
			params.addAll(collection);
		}else if( value.getClass().isArray() ){
			Object[] array=(Object[])value;
			length=array.length;
			Collections.addAll(params,array);
		}else {
			length=1;
			params.add(value);
		}
		StringBuffer sb=new StringBuffer();
		for(int i=0;i<length;i++){
			sb.append("?");
			if( i+1<length )
				sb.append(",");
		}
		return sb.toString();
	}


	/**通过反射获取属性
	 * @param obj
	 * @param key
	 * @return
	 */
	private  Object getProperty(Object obj,String key){
		if(obj == null)
			return null;
		try {
			return PropertyUtils.getProperty(obj, key);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**行记录转换pojo
	 * @param cls
	 * @return
	 */
	private <T> RowMapper<T> rowMapper(final Class<T> cls){
		return new RowMapper<T>(){

			private ConcurrentHashMap<String,Method> successCache;//不需要类型转换的
			private ConcurrentHashMap<String,PropertyDescriptor> converCache;//需要类型转换的

			@Override
			public T mapRow(ResultSet rs, int rowNum) throws SQLException {
				if(rowNum==0){  //初始化mapping 需要的缓存
					initCache(rs.getMetaData());
				}

				T object= null;
				try {
					object = cls.newInstance();
				} catch (Exception e) {

				}
				if(object==null){
					return null;
				}

				for(Map.Entry<String, Method> entry : successCache.entrySet()){ //不需要转换的字段

					setValue(entry.getValue(),object, getValue(rs,entry.getKey()));

				}

				for(PropertyDescriptor propertyDescriptor : converCache.values()){ //需要用到类型转换的字段
					String name=propertyDescriptor.getName();
					Object value=getValue(rs,name);
					if( value!=null ){
						Class<?> trgetClass=propertyDescriptor.getPropertyType();
						Method method=propertyDescriptor.getWriteMethod();
						if(value.getClass() == trgetClass || value.getClass().getSuperclass()==trgetClass){
							setValue(method,object,value);
							converCache.remove(name);
							successCache.put(name,method);
						}else{
							setValue(method,object,value,trgetClass);
						}
					}
				}
				return object;
			}

			//从结果集中获取value
			private Object getValue(ResultSet rs,String key){
				if(key != null){
					try{
						return rs.getObject(key);
					}catch (Exception e){
						
					}
				}
				return null;
			}

			//需要转换设置value
			private void setValue(Method method,Object trget,Object value,Class<?> trgetClass){
				if(value != null){
					try{
						method.invoke(trget, ConvertUtils.convert(value,trgetClass));
					}catch (Exception e){

					}
				}
			}

			//需要转换设置value
			private void setValue(Method method,Object trget,Object value){
				if(value != null){
					try{
						method.invoke(trget,value);
					}catch (Exception e){
						
					}
				}
			}


			//初始化mapping缓存
			private void initCache(ResultSetMetaData rmd){ //缓存mapping 以加快转换的速度

				converCache=new ConcurrentHashMap<String, PropertyDescriptor>();
				successCache=new ConcurrentHashMap<String,Method>();

				PropertyDescriptor [] propertyDescriptors = PropertyUtils.getPropertyDescriptors(cls);
				for(PropertyDescriptor propertyDescriptor : propertyDescriptors){

                    if( !propertyDescriptor.getName().equalsIgnoreCase("class") )
					    converCache.put(propertyDescriptor.getName(), propertyDescriptor);
				}
				try {
					for(int i=1;i<rmd.getColumnCount();i++){
						String name=rmd.getColumnLabel(i);
						if( !converCache.containsKey(name) ){
							converCache.remove(name);
						}
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		};
	}

	class SqlAndParams{
		private String sql;
		private List<Object> params;

		public SqlAndParams(){
			params=new ArrayList<Object>();
		}

		public SqlAndParams(List<Object> params){
			this.params=params;
		}

		public String getSql() {
			return sql;
		}

		public void setSql(String sql) {
			this.sql = sql;
		}

		public List<Object> getParams() {
			return params;
		}

		public void setParams(List<Object> params) {
			this.params = params;
		}


	}

	public static void main(String ... args) throws HossSqlException {
		PropertyDescriptor [] propertyDescriptors = PropertyUtils.getPropertyDescriptors(Broker.class);
		for(PropertyDescriptor propertyDescriptor : propertyDescriptors){

			//      	  converCache.put(key, value)
			System.out.println(propertyDescriptor.getName());
			//      	  propertyDescriptor.getWriteMethod()
			//      	  propertyDescriptor.getName()
			//      	  propertyDescriptor.getPropertyType()
		}
	}

}

 

你可能感兴趣的:(JdbcTemplate)