导读:

主要从4个方面来阐述,1:背景;2:思路;3:代码实现;4:使用

一:封装背景,

在做项目的时候,用的JPA ,有些复杂查询,比如报表用原生的JdbcTemplate ,很不方便,传参也不方便,如果参数多;需要增加分页功能,以及结果集自动转对像等5个常用功能,见第4节

下面两个图是开源测试管理软件 itest 的统计功能,因为SQL复杂,有些有200行,所以才有后面的 JdbcTemplateWrapper;可以在这体验这些报表(点测试,然后选择一个项目,然后点度量分析),速度还不错,https://itest.work/rsf/site/itest/product/index.html

上面这图,SQL 就有200行

二:封装实现思路

(1)实现spring RowMapper 接口,直接把jdbc 结果集转 JAVA 对像(用的反射,访问量大的业务不推荐用这方式)

(2)不通过 RowMapper 接口, 把JdbcTemplate 返回的List<Map<String,Object>>  原生JDBC结果集中,字段名,也就是MAP中的KEY,转换为驼峰规则的JAVA对属性名,方便前端组件使用,不再中间转为VO 或 实体类对像后,再返前端;比传统查询(多了一个LIST的遍历 ,基本对性能影响不大)

(3)封装分页

(4) 在  JdbcTemplateWrapper 中包装 NamedParameterJdbcTemplate 解决友好传参的问题,再封几个常用的查询方法,可变长参数,或是以MAP形式传参数 key 为SQL中的参数名占位符

三:代码实现

   两个类,ObjectRowMapper   和  JdbcTemplateWrapper

ObjectRowMapper    代码如下:

package cn.com.mypm.framework.jdbc;import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.util.StringUtils;import cn.com.mypm.common.util.CalendaUtilities;
import cn.com.mypm.framework.common.config.PropertiesBean;/***
* <p>标题: RowMapper 接口实现</p>
* <p>业务描述:完成原生结果集到JAVA对像的转换</p>
* <p>公司:itest.work</p>
* <p>版权:itest 2018</p>
* @author itest andy
* @date 2018年6月8日
* @version V1.0*/
@SuppressWarnings("rawtypes")
public class ObjectRowMapper implements RowMapper {private Class<?> objectClass;private String[] columnNames = null;private Field[] fields ;///缓存 当前结果集字对段和当前class的 Field的对应关系,private Map<String ,Field> currQueryFieldMap ;//缓存当前结果集,字段和 JAVA属性名的对应关系 ,按脱峰规则做的转换private Map<String ,String> fieldClassMap ;private Boolean isConvertSwitch  = null;// MYSQL 是否区分大小写的标记,要是区转,要把结果集中,字段名,大写转为小写private String mysqlLowerCaseTableNames = null;private static Log logger = LogFactory.getLog(ObjectRowMapper.class);//缓存某个class 已处理过的字段映射到属性名的关系,避免同一个类每次重新处理,第一个KEY 为类名private static Map<String, Map<String, String>> dbColumnClassFieldMap = new ConcurrentHashMap<String, Map<String, String>>();public ObjectRowMapper(Class<?> objectClass) {this.objectClass = objectClass;fields = objectClass.getDeclaredFields();}public void clean(){if(currQueryFieldMap!=null){currQueryFieldMap.clear();currQueryFieldMap = null;}if(fieldClassMap!=null){fieldClassMap.clear();fieldClassMap = null;}if(fields!=null){fields = null;}if(columnNames!=null){columnNames = null;}}/*** 该方法自动将数据库字段对应到Object中相应字段 要求:* 字段名严格为驼峰形式 == 数据库字段名去掉下划线转为驼峰形式* 如user_name 转为userName ,如数据库字段名,无下划线* 就只能把首字母变为大小写后的 set ,get*/@Overridepublic Object mapRow(ResultSet rs, int rowNum) throws SQLException {Object targetObject = null;try {targetObject = objectClass.newInstance();} catch (InstantiationException | IllegalAccessException e) {logger.error(e.getMessage(), e);}if (columnNames == null) {ResultSetMetaData rsmd = rs.getMetaData();int columnCount = rsmd.getColumnCount();columnNames = new String[columnCount];for (int i = 0; i < columnCount; i++) {columnNames[i] = rsmd.getColumnLabel(i + 1);}}isConvertSwitch = true;if(mysqlLowerCaseTableNames == null){String lowerCaseNames = PropertiesBean.getInstance().getProperty("conf.mysql.lowerCaseNames");if(lowerCaseNames==null){mysqlLowerCaseTableNames = "yes";}else{mysqlLowerCaseTableNames = "no";}}if(currQueryFieldMap==null){currQueryFieldMap = new HashMap<String,Field>(columnNames.length);for (String columnName : columnNames) {for (Field field : fields) {if(isConvertSwitch==null){if (field.getName().equals(convertColumnNameToFieldName(columnName))) {currQueryFieldMap.put(columnName, field);break;}}else{if(isConvertSwitch){if(targetObject instanceof  CustomRowMapper&&(!((CustomRowMapper)targetObject).isConvert())){if (field.getName().equals(columnName)) {currQueryFieldMap.put(columnName, field);break;}}else{if (field.getName().equals(convertColumnNameToFieldName(columnName))) {currQueryFieldMap.put(columnName, field);break;}}}}}}}for (String columnName : columnNames) {Field field = currQueryFieldMap.get(columnName);if(field==null){if(logger.isDebugEnabled()){logger.debug(objectClass.getName() +"is  not property match  db columnName:"+columnName );}continue;}Object value = rs.getObject(columnName);if (value == null) {continue;}boolean accessFlag = field.isAccessible();if (!accessFlag) {field.setAccessible(true);}if(fieldClassMap==null){fieldClassMap = new HashMap<String,String>(columnNames.length);}if(fieldClassMap.get(columnName)==null){fieldClassMap.put(columnName, getFieldClaszName(field));}setFieldValue(targetObject, field, rs, columnName,fieldClassMap.get(columnName));// 恢复相应field的权限if (!accessFlag) {field.setAccessible(accessFlag);}}return targetObject;}public String convertColumnNameToFieldName(String columnName) {Map<String, String> fieldMap = dbColumnClassFieldMap.get(objectClass.getName());boolean emptyFlg = false;if (fieldMap == null) {fieldMap = new HashMap<String, String>();emptyFlg = true;}String classFieldName = fieldMap.get(columnName);if (classFieldName != null) {return classFieldName;}String columnNameKey = columnName;//if ("oracle".equals(dbType)||("mysql".equals(dbType)&&"no".equals(mysqlLowerCaseTableNames))) {columnName = columnName.toLowerCase();//}StringBuffer buf = new StringBuffer();int i = 0;while ((i = columnName.indexOf('_')) > 0) {buf.append(columnName.substring(0, i));columnName = StringUtils.capitalize(columnName.substring(i + 1));}buf.append(columnName);fieldMap.put(columnNameKey, buf.toString());if (emptyFlg) {dbColumnClassFieldMap.put(objectClass.getName(), fieldMap);}return fieldMap.get(columnNameKey);}/*** 根据类型对具体对象属性赋值*/public static void setFieldValue(Object targetObj, Field field,ResultSet rs, String columnLabel,String fieldClass) {try {if ("String".equals(fieldClass)) {field.set(targetObj, rs.getString(columnLabel));} else if ("Double".equals(fieldClass)) {field.set(targetObj, rs.getDouble(columnLabel));} else if ("Float".equals(fieldClass)) {field.set(targetObj, rs.getFloat(columnLabel));} else if ("Integer".equals(fieldClass)) {field.set(targetObj, rs.getInt(columnLabel));} else if ("Long".equals(fieldClass)) {field.set(targetObj, rs.getLong(columnLabel));} else if ("BigDecimal".equals(fieldClass)) {field.set(targetObj, rs.getBigDecimal(columnLabel));} else if ("Date".equals(fieldClass)) {field.set(targetObj, rs.getDate(columnLabel));} else if ("Short".equals(fieldClass)) {field.set(targetObj, rs.getShort(columnLabel));} else if ("Boolean".equals(fieldClass)) {field.set(targetObj, rs.getBoolean(columnLabel));} else if ("Byte".equals(fieldClass)) {field.set(targetObj, rs.getByte(columnLabel));} else if ("Timestamp".equals(fieldClass)) {field.set(targetObj, rs.getTimestamp(columnLabel));} else if("BigDecimal".equals(fieldClass)) {field.set(targetObj, rs.getBigDecimal(columnLabel));}else {//这里没有实现,如有特殊需要处理的在这里实现}} catch (IllegalArgumentException e) {logger.error(e.getMessage(), e);} catch (IllegalAccessException e) {logger.error(e.getMessage(), e);} catch (SQLException e) {logger.error(e.getMessage(), e);}}private static String getFieldClaszName(Field field) {String elemType = field.getType().toString();if ("class java.lang.String".equals(elemType)|| elemType.indexOf("char") != -1|| elemType.indexOf("Character") != -1) {return "String";} else if (elemType.indexOf("double") != -1|| elemType.indexOf("Double") != -1) {return "Double";} else if (elemType.indexOf("float") != -1|| elemType.indexOf("Float") != -1) {return "Float";} else if (elemType.indexOf("int") != -1|| elemType.indexOf("Integer") != -1||elemType.indexOf("BigInteger") != -1) {return "Integer";} else if (elemType.indexOf("long") != -1|| elemType.indexOf("Long") != -1) {return "Long";} else if (elemType.indexOf("BigDecimal") != -1) {return "BigDecimal";} else if (elemType.indexOf("Date") != -1) {return "Date";} else if (elemType.indexOf("short") != -1|| elemType.indexOf("Short") != -1) {return "Short";} else if (elemType.indexOf("boolean") != -1|| elemType.indexOf("Boolean") != -1) {return "Boolean";} else if (elemType.indexOf("byte") != -1|| elemType.indexOf("Byte") != -1) {return "Byte";}  else if (elemType.indexOf("Timestamp") != -1) {return "Timestamp";}return "String";}

JdbcTemplateWrapper

package cn.com.mypm.framework.jdbc;import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.util.Assert;import cn.com.mypm.common.dto.PageModel;
import cn.com.mypm.framework.exception.DataBaseException;/***
* <p>标题:  JdbcTemplate 包装器</p>
* <p>业务描述:实现分页,原生结果集转对像,原生结果集字段名转脱峰java 属性名</p>
* <p>公司:itest.work</p>
* <p>版权:itest 2018</p>
* @author itest andy
* @date 2018年6月8日
* @version V1.0*/
public class JdbcTemplateWrapper  {private static Log logger = LogFactory.getLog(JdbcTemplateWrapper.class);private JdbcTemplate jdbcTemplate;private String dbType = "mysql";private String showSql = "false";protected NamedParameterJdbcTemplate namedParameterJdbcTemplate;private String mysqlLowerCaseTableNames = null;public JdbcTemplateWrapper() {super();}public JdbcTemplateWrapper(JdbcTemplate jdbcTemplate) {super();this.jdbcTemplate = jdbcTemplate;this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);}public JdbcTemplateWrapper(JdbcTemplate jdbcTemplate, String dbType, String showSql) {super();this.jdbcTemplate = jdbcTemplate;this.dbType = dbType;this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);this.showSql = showSql;}public JdbcTemplate getJdbcTemplate() {return jdbcTemplate;}/*** 查询所有匹配的列表* * @param sql*            查询sql* @param className*            对象类型* @param args*            查询参数* @return* @author itest andy */@SuppressWarnings({ "rawtypes", "unchecked" })public List queryAllMatchList(String sql, Class clasz, Object[] args) {Assert.notNull(clasz, "clasz must not be null");List dataList = null;RowMapper rowMapper = new ObjectRowMapper(clasz);dataList = getJdbcTemplate().query(sql, args, rowMapper);((ObjectRowMapper) rowMapper).clean();rowMapper = null;return dataList;}/*** 查询所有匹配的列表* * @param sql*            查询sql* @param className*            对象类型* @param args*            查询参数* @return* @author itest andy */@SuppressWarnings({ "rawtypes", "unchecked" })public List queryAllMatchListWithFreePra(String sql, Class clasz, Object... args) {Assert.notNull(clasz, "clasz must not be null");List dataList = null;RowMapper rowMapper = new ObjectRowMapper(clasz);dataList = getJdbcTemplate().query(sql, args, rowMapper);((ObjectRowMapper) rowMapper).clean();rowMapper = null;return dataList;}/*** 把list map 原生JDBC结果集中,字段名,也就是MAP中的KEY,转换为驼峰规则的JAVA对属性名* * @param resultList :JDBC 结果集* @return    把MAP中的KEY转换为转换为驼峰规则的JAVA对属性名的LIST<map<驼峰规则的JAVA对属性名形式的KEY,Object>>* @author itest andy */public void converDbColumnName2ObjectPropName(List<Map<String,Object>> resultList) {if(resultList!=null&&!resultList.isEmpty()) {List<Map<String,Object>> convertList=  new ArrayList<Map<String,Object>>(resultList.size());//用于缓存字段名到属性名的映射,第二条记录时就不再处理字段名到属性名的转换,提升性能Map<String,String> ColumnNamePropNameMap = null;if(resultList.size()>1) {ColumnNamePropNameMap = new HashMap<String,String>();}for(Map<String,Object> currMap :resultList) {if(currMap!=null&&!currMap.isEmpty()) {Iterator<Entry<String, Object>>   currentIt =  currMap.entrySet().iterator();Map tempMap = new HashMap<String,Object>();convertList.add(tempMap);while(currentIt.hasNext()) {Map.Entry<String,Object>  me=  currentIt.next();String dbColumnName = me.getKey();Object value = me.getValue();if(resultList.size()>1) {if(ColumnNamePropNameMap.get(dbColumnName)==null) {String currProName = convertColumnName2OFieldName(dbColumnName);tempMap.put(currProName, value);//缓存起来,第二条记录时就不再处理字段名到属性名的转换,提升性能ColumnNamePropNameMap.put(dbColumnName, currProName);}else {tempMap.put(ColumnNamePropNameMap.get(dbColumnName), value);}}else {tempMap.put(convertColumnName2OFieldName(dbColumnName), value);}}}}resultList.clear();for(Map<String,Object> currMap:convertList) {resultList.add(currMap);}convertList.clear();convertList = null;}}public String convertColumnName2OFieldName(String columnName ) {if(mysqlLowerCaseTableNames == null){String lowerCaseNames = PropertiesBean.getInstance().getProperty("conf.mysql.lowerCaseNames");if(lowerCaseNames==null){mysqlLowerCaseTableNames = "yes";}else{mysqlLowerCaseTableNames = "no";}}if ("oracle".equals(dbType)||("mysql".equals(dbType)&&"no".equals(mysqlLowerCaseTableNames))) {columnName = columnName.toLowerCase();}if("true".equals(mysqlLowerCaseTableNames)) {columnName = columnName.toLowerCase();}StringBuffer buf = new StringBuffer();int i = 0;while ((i = columnName.indexOf('_')) > 0) {buf.append(columnName.substring(0, i));columnName = StringUtils.capitalize(columnName.substring(i + 1));}buf.append(columnName);return  buf.toString();}/*** 查询所有匹配的列表* * @param sql*            查询sql* @param className*            对象类型* @param paramMap*            查询参数* @return* @author itest andy */@SuppressWarnings({ "rawtypes", "unchecked" })public List queryAllMatchListWithParaMap(String sql, Class clasz, Map paramMap) {if (paramMap != null && paramMap.isEmpty()) {paramMap = null;}if ("true".equals(showSql)) {try {logger.info(getSqlFromQueryData(sql, paramMap));} catch (Exception e) {logger.error(e.getMessage(), e);}}List resultList = null;if (clasz == null) {resultList = namedParameterJdbcTemplate.queryForList(sql, paramMap);} else {RowMapper rowMapper = new ObjectRowMapper(clasz);resultList = namedParameterJdbcTemplate.query(sql, paramMap, rowMapper);((ObjectRowMapper) rowMapper).clean();rowMapper = null;}return resultList;}/*** * @param pageModel:* @param className*            : 从查询结果集中构建出的类,如为null则pageModel的PageData为List<Map>,*            不为null则pageModel的PageData为List<className>* @param columnNameForCount:查询记录数时的字段名,一般用主键*/@SuppressWarnings({ "rawtypes", "unchecked" })public void fillPageModelData(PageModel pageModel, Class className, String columnNameForCount) {if (pageModel.getHqlParamMap() != null && pageModel.getHqlParamMap().isEmpty()) {pageModel.setHqlParamMap(null);}if (pageModel.getTotal() == 0) {int totalRows = this.getResultCountWithValuesMap(pageModel.getQueryHql(), columnNameForCount,pageModel.getHqlParamMap());pageModel.setTotal(totalRows);}if (pageModel.getTotal() == 0) {pageModel.setRows(new ArrayList());return;}if (pageModel.getPageNo() > 1) {int pageCount = this.getValidPage(pageModel.getPageNo(), pageModel.getTotal(), pageModel.getPageSize());if (pageCount < pageModel.getPageNo()) {pageModel.setPageNo(pageCount);}}int startRow = getStartOfPage(pageModel.getPageNo(), pageModel.getPageSize());String sql = this.buildPageSql(pageModel.getQueryHql(), startRow, pageModel.getPageSize());if ("true".equals(showSql)) {try {logger.info(getSqlFromQueryData(sql, pageModel.getHqlParamMap()));} catch (Exception e) {logger.error(e.getMessage(), e);}}List dataList = null;if (className == null) {dataList = namedParameterJdbcTemplate.queryForList(sql, pageModel.getHqlParamMap());} else {RowMapper rowMapper = new ObjectRowMapper(className);dataList = namedParameterJdbcTemplate.query(sql, pageModel.getHqlParamMap(), rowMapper);((ObjectRowMapper) rowMapper).clean();rowMapper = null;}pageModel.setRows(dataList);}/*** 多表sql 分页查询,多表连查时,才用这个方法,其他请用commonDao的 SQL分页查询* * @param sql* @param className* @param paramMap* @param pageNo* @param PageSize* @param columnNameForCount* @return*/@SuppressWarnings({ "rawtypes", "unchecked" })public List queryAllMatchListWithParaMap(String sql, Class clasz, Map paramMap, int pageNo, int pageSize,String columnNameForCount) {if (paramMap != null && paramMap.isEmpty()) {paramMap = null;}if ("true".equals(showSql)) {try {logger.info(getSqlFromQueryData(sql, paramMap));} catch (Exception e) {logger.error(e.getMessage(), e);}}
//         int totalRows = this.getResultCountWithValuesMap(sql,
//         columnNameForCount, paramMap);
//         if(pageNo>1){
//             int pageCount = this.getValidPage(pageNo, totalRows, pageSize);
//         }List resultList = null;int startRow = getStartOfPage(pageNo, pageSize);if (clasz == null) {resultList = namedParameterJdbcTemplate.queryForList(this.buildPageSql(sql, startRow, pageSize), paramMap);} else {RowMapper rowMapper = new ObjectRowMapper(clasz);resultList = namedParameterJdbcTemplate.query(this.buildPageSql(sql, startRow, pageSize), paramMap,rowMapper);rowMapper = null;}return resultList;}private String buildPageSql(String sql, int startRow, int pageSize) {if ("oracle".equals(this.getDbType())) {return this.buildOraclePageSql(sql, startRow, pageSize);} else if ("mysql".equals(this.getDbType())) {return this.buildMysqlPageSql(sql, startRow, pageSize);} else if ("informix".equals(this.getDbType())) {return this.buildInformixPageSql(sql, startRow, pageSize);}throw new DataBaseException("don't support db type,please confirm db is oracle or mysql or informix");}private String buildOraclePageSql(String sql, int startRow, int pageSize) {StringBuilder pageSql = new StringBuilder("SELECT * FROM  ");pageSql.append(" ( ");pageSql.append(" SELECT pageDataTable.*, ROWNUM RNV ");pageSql.append(" FROM (" + sql + " ) pageDataTable ");pageSql.append(" WHERE ROWNUM <= " + (startRow + pageSize));pageSql.append(" )  WHERE RNV >= " + (startRow + 1));return pageSql.toString();}private String buildMysqlPageSql(String sql, int startRow, int pageSize) {sql = sql + " limit " + startRow + ", " + pageSize;return sql;}private String buildInformixPageSql(String sql, int startRow, int pageSize) {sql = sql.trim();if (sql.startsWith("select")) {sql = sql.replaceFirst("select", " select skip " + startRow + " first " + pageSize + " ");} else {sql = sql.replaceFirst("SELECT", " select skip " + startRow + " first " + pageSize + " ");}return sql;}private Integer getValidPage(Integer pageNo, int totalRows, Integer pageSize) {if (!isValidPage(pageNo, totalRows, pageSize)) {return getValidPage(--pageNo, totalRows, pageSize);}int pageCount = (totalRows + (pageSize - (totalRows % pageSize == 0 ? pageSize : totalRows % pageSize)))/ pageSize;return pageCount;}private static int getStartOfPage(int pageNo, int pageSize) {if(pageNo==0){pageNo=1;}return (pageNo - 1) * pageSize;}private boolean isValidPage(Integer pageNo, Integer totalRows, Integer pageSize) {if (pageNo == 1) {return true;}int rowStart = (pageNo - 1) * pageSize;int rowEnd = rowStart + pageSize;if (rowEnd > totalRows) {rowEnd = totalRows;}return rowEnd > rowStart;}/*** 查询记录数* * @param sql* @param columnNameForCount* @param praValuesMap* @return*/// @SuppressWarnings("deprecation")public int getResultCountWithValuesMap(String sql, String columnNameForCount, Map<String, Object> praValuesMap) {if (praValuesMap != null && praValuesMap.isEmpty()) {praValuesMap = null;}String countQuerySql = null;countQuerySql = " select count(*) from ( " + sql + " ) V_TABLE";return namedParameterJdbcTemplate.queryForInt(countQuerySql, praValuesMap);}public int queryForIntWithpraValuesMap(String countQuerySql, Map<String, Object> praValuesMap) {if (praValuesMap != null && praValuesMap.isEmpty()) {praValuesMap = null;}return namedParameterJdbcTemplate.queryForInt(countQuerySql, praValuesMap);}public int queryForInt(String countQuerySql, Object... args) {return getJdbcTemplate().queryForInt(countQuerySql, args);}public static String getSqlFromQueryData(String sql, Map<String, Object> paramMap) {if (StringUtils.isEmpty(sql)) {return null;}if (paramMap == null) {return sql;}StringBuffer sqlExp = new StringBuffer(sql);Set<Entry<String, Object>> set = paramMap.entrySet();for (Entry<String, Object> entry : set) {int start = sqlExp.indexOf(":" + entry.getKey() + " ");if (start < 0) {continue;}int last = sqlExp.lastIndexOf(":" + entry.getKey() + " ");if (start >= 0 && start == last) {if (entry.getValue() != null) {sqlExp.replace(start, start + entry.getKey().length(), "'" + entry.getValue().toString() + "'");// sqlExp.replace(start-1, start+entry.getKey().length(),// "'"+entry.getValue().toString()+"'");}} else {// 处理同一参数多处出现sqlExp.replace(start, start + entry.getKey().length(), "'" + entry.getValue().toString() + "'");start = sqlExp.indexOf(":" + entry.getKey());while (start > 0) {sqlExp.replace(start, start + entry.getKey().length(), "'" + entry.getValue().toString() + "'");start = sqlExp.indexOf(":" + entry.getKey());}}}return sqlExp.toString();}private static String removeSelect(String sql) {int beginPos = sql.indexOf(" from ");if (beginPos < 0) {beginPos = sql.indexOf("from ");}if (beginPos < 0) {beginPos = sql.toLowerCase().indexOf(" from ");}if (beginPos < 0) {beginPos = sql.toLowerCase().indexOf("from ");}return sql.substring(beginPos);}/*** 去除sql的orderby 用于页查果询* * @param sql* @return*/private static String removeOrders(String sql) {Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);Matcher m = p.matcher(sql);StringBuffer sb = new StringBuffer();while (m.find()) {m.appendReplacement(sb, "");}m.appendTail(sb);return sb.toString();}public String getDbType() {return dbType;}public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {return namedParameterJdbcTemplate;}public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);}public String getMysqlLowerCaseTableNames() {return mysqlLowerCaseTableNames;}public void setMysqlLowerCaseTableNames(String mysqlLowerCaseTableNames) {this.mysqlLowerCaseTableNames = mysqlLowerCaseTableNames;}public String isShowSql() {return showSql;}public void setShowSql(String showSql) {this.showSql = showSql;}}

三:使用

数据源和JPA是同一数据源,在同一事务中,用的连接和JPA使用的是同一个连接,在CommonDao 额外注入一个  JdbcTemplateWrapper,当作处理复杂SQL的帮手。

JdbcTemplateWrapper  常用的方法同如下几个:

clasz 把查询结果要转为的类对像,内部再构造 ObjectRowMapper

1:public List queryAllMatchListWithFreePra(String sql, Class clasz, Object... args)  // SQL 参数为问号占位符,使用参数个数<=3 个时的情况,可以用要不参数多了,可变长参数多,阅读性差

2:public List queryAllMatchListWithParaMap(String sql, Class clasz, Map paramMap) // SQL 参数,为 参数名占位符 ,如 name=:name, paramMap中 key 为参数名,value 为值数值(用于参数个数多于3时,用参数名占位符的方式,然后用Map 传参) ; 如clasz 传为为空,实际返为 List<Map<String,Object>>,不为空侧为   List<Map<String,clasz>>

3:  以pageModel为载体实现分页

/**
     *
     * @param pageModel: 设置了查询SQL ,及查询参数 Map paramMap 的分页对像
     * @param className
     *            : 从查询结果集中构建出的类,如为null则pageModel的PageData为List<Map>,
     *            不为null则pageModel的PageData为List<className>
     * @param columnNameForCount:查询记录数时的字段名,一般用主键
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void fillPageModelData(PageModel pageModel, Class className)

4  : 不用 pageModel 分页查询

/**
     * 多表sql 分页查询,多表连查时,才用这个方法,其他请用commonDao的 SQL分页查询
     *
     * @param sql
     * @param className
     * @param paramMap
     * @param pageNo
     * @param PageSize
     * @param columnNameForCount
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public List queryAllMatchListWithParaMap(String sql, Class clasz, Map paramMap, int pageNo, int pageSize)

5 : 把list map 原生JDBC结果集中,字段名,也就是MAP中的KEY,转换为驼峰规则的JAVA对属性名

/**
     * 把list map 原生JDBC结果集中,字段名,也就是MAP中的KEY,转换为驼峰规则的JAVA对属性名
     * 方便前端组件使用,不再中间转为VO 或 实体类对像后,再返前端;比传统查询(多了一个LIST的遍历 ,基本对性能影响不大)
     * @param resultList :JDBC 结果集
     * @return    把MAP中的KEY转换为转换为驼峰规则的JAVA对属性名的LIST<map<驼峰规则的JAVA对属性名形式的KEY,Object>>
     * @author itest andy
     */
    public void converDbColumnName2ObjectPropName(List<Map<String,Object>> resultList)

转自本人在博客园的原创  ,在这里还算不算原创?

spring JdbcTemplate 在项目中的浅层(5个使用场景)封装相关推荐

  1. 重新学习Spring一--Spring在web项目中的启动过程

    1 Spring 在web项目中的启动过程 Spring简介 Spring 最简单的功能就是创建对象和管理这些对象间的依赖关系,实现高内聚.低耦合.(高内聚:相关性很强的代码组成,既单一责任原则:低耦 ...

  2. 异常检测中的浅层模型与深度学习模型综述(A Unifying Review of Deep and Shallow Anomaly Detection)

    A Unifying Review of Deep and Shallow Anomaly Detection 异常检测中的浅层模型与深度学习模型综述 摘要:随着众多异常检测方法(基于生成模型,单分类 ...

  3. iOS项目中的网络请求和上下拉刷新封装

    代码地址如下: http://www.demodashi.com/demo/11621.html 一.运行效果图 现在的项目中不可避免的要使用到网络请求,而且几乎所有软件都有上下拉刷新功能,所以我在此 ...

  4. Android项目中多次操作SharedPreferences导致ANR场景的解决

    系列文章目录 Android项目中多次操作SharedPreferences导致ANR场景的解决 文章目录 系列文章目录 项目背景: 以定位来获取广告的方式为例: 所遇到的挑战: 解决问题的步骤: 问 ...

  5. 在 Java Web 项目中,Service 层和 Dao 层真的有必要每个类都加上接口吗

    作者 l 会点代码的大叔(CodeDaShu) 很多程序员在刚开始工作的时候,接触到的项目都是这样做的:项目的代码被分成 Controller.Service.Dao 层,一个接口对应一个实现类,然后 ...

  6. Spring 配置的项目中数据库链接信息加密(详细)

    传统JAVA_WEB项目如果是ssh.ssm之类的搭建的项目,其数据库链接信息大部分是交给Spring来作为管理 数据库的URL地址.账号.密码一般会写在配置文件中:dbconfig.properti ...

  7. Spring Boot+JSP项目中静态资源配置

    Spring Boot静态资源配置说明 在 Spring Boot 中,默认情况下,一共有5个位置可以放静态资源,五个路径分别如下: classpath:/META-INF/resources/ cl ...

  8. java spring异常处理_Spring项目中优雅的异常处理

    前言 如今的Java Web项目多是以 MVC 模式构建的,通常我们都是将 Service 层的异常统一的抛出,包括自定义异常和一些意外出现的异常,以便进行事务回滚,而 Service 的调用者 Co ...

  9. 公司项目中的biz层和manager层是干啥的

    我们都知道熟悉的三层架构: mapper(dao)层:数据传输对象,一般是把数据库表封装成对象,表的各个字段就是该对象的各个变量. service层:相对具体的业务逻辑服务层. controller层 ...

最新文章

  1. UVA 216 Getting in Line
  2. oracle导入索引b报错,impdp导入索引很慢
  3. P1912 [NOI2009]诗人小G
  4. 【编程通识】PlantUML绘制时序图样例
  5. qt样式表中背景图片的使用
  6. 字符串转数字测试--知识备忘
  7. 什么!卷积要旋转180度?!
  8. cocos2d-x学习笔记番外篇05:如何快速屏蔽触摸
  9. 《Puppet实战手册》——导读
  10. myeclipse中加入jad查看jar源代码
  11. 安装sql2012 正在启动操作系统功能NetFx3
  12. EXPLAIN查看SQL执行计划
  13. 工业互联网常用无线通信协议介绍(详细版)
  14. php爬虫教程(二)数据请求分析
  15. 爆炸三角形如何用计算机实现,爆炸三角形原理
  16. unity材质球复制
  17. mysql order field_mysql 使用order by filed,locate和instr自定义排序
  18. 人工智能编程语言介绍
  19. 百度之星Valley Numer
  20. PostGis部分点线相关函数测试

热门文章

  1. Web访问RabbitMQ
  2. Linux上安装paramiko模块
  3. xilinx中IP核是灰色的 license为带美元的小锁
  4. 【书评】OSPF Anatomy of an Internet Routing Protocol
  5. 2.2. 对网络安全的威胁
  6. Javascript 节点 全面解析
  7. 云服务器基础运维与管理
  8. EBS R12中如何使用CGI登录Form
  9. CentOS网络配置
  10. HQL语句中数据类型转换,及hibernate中createQuery执行hql报错