package com.taover.repository; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.persistence.Column; import javax.persistence.Id; import javax.persistence.Table; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.jdbc.core.ArgumentPreparedStatementSetter; import org.springframework.jdbc.core.PreparedStatementCreator; import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; import com.taover.repository.exception.MultiRowException; import com.taover.repository.exception.NoContainTenantException; import com.taover.repository.exception.NotFoundException; import com.taover.repository.exception.ObjectReflectException; import com.taover.repository.jdbctemplate.JdbcTemplateBroadcast; import com.taover.repository.mapper.CustomJdbcTemplateRowMapper; import com.taover.repository.util.UtilsSql; /** * * @author root * * @param * @param */ public class CustomJdbcTemplateBroadcast implements CustomJdbcTemplateBroadcastInterface{ @Resource private JdbcTemplateBroadcast _jdbcTemplateBroadcast; private Map _beanToTableField; private Map _tableToBeanField; private String _tableFieldNameListGapWithComma; private String _idTableFieldName; private String _dbName; private String _tableName; private Class _tClassInfo; private CustomJdbcTemplateRowMapper _customJdbcTemplateRowMapper; public CustomJdbcTemplateRowMapper getCustomJdbcTemplateRowMapper(){ return this._customJdbcTemplateRowMapper; } @SuppressWarnings("unchecked") public CustomJdbcTemplateBroadcast() throws Exception{ //获取泛型类Class this._tClassInfo = (Class)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]; //检查实体声明 Table annoTable = (Table) _tClassInfo.getAnnotation(Table.class); if(annoTable == null){ throw new Exception("DAO层初始化失败,失败原因:"+_tClassInfo.getName()+"实体类,没有@Table注解指定表名"); } this._tableName = annoTable.name(); String schema = annoTable.schema(); String catalog = annoTable.catalog(); if(schema != null && !"".equals(schema)){ this._dbName = schema; }else if(catalog != null && !"".equals(catalog)){ this._dbName = catalog; } //初始化数据 _beanToTableField = new HashMap(); _tableToBeanField = new HashMap(); _tableFieldNameListGapWithComma = ""; Field[] declaredFields = _tClassInfo.getDeclaredFields(); for(int i=0; i(this._tClassInfo, this._tableToBeanField); } /** * 将驼峰式命名的字符串转换为下划线大写方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。
* 例如:HelloWorld->HELLO_WORLD * @param name 转换前的驼峰式命名的字符串 * @return 转换后下划线大写方式命名的字符串 */ private String camelToUnderline(String name) { StringBuilder result = new StringBuilder(); if (name != null && name.length() > 0) { // 将第一个字符处理成大写 result.append(name.substring(0, 1).toUpperCase()); // 循环处理其余字符 for (int i = 1; i < name.length(); i++) { String s = name.substring(i, i + 1); // 在大写字母前添加下划线 if (Character.isUpperCase(s.charAt(0)) && Character.isLetter(s.charAt(0))) { result.append("_"); } // 其他字符直接转成大写 result.append(s.toUpperCase()); } } return result.toString(); } private void appendWhereCondition(StringBuffer sql, StringBuffer pql, List list, List condition) { if (condition == null || condition.size() == 0) return; Object[] con = condition.get(0); int iLen = condition.size(); sql.append(" WHERE "); pql.append(" WHERE "); sql.append(con[0]); pql.append(con[0]); if (null != con[1] && con[1] != "" && con[1] != "useArg[0]") { sql.append(" " + con[1] + " ?"); pql.append(" " + con[1] + " " + con[2]); list.add(con[2]); } for (int i = 1; i < iLen; i++) { con = condition.get(i); sql.append(" AND "); pql.append(" AND "); sql.append(con[0]); pql.append(con[0]); if (null == con[1] || "" == con[1] || con[1] == "useArg[0]") continue; sql.append(" " + con[1] + " ?"); pql.append(" " + con[1] + " " + con[2]); list.add(con[2]); } } private void appendWhereConditionForCount(StringBuffer sql, List condition) { if (condition == null || condition.size() == 0) return; Object[] con = condition.get(0); int iLen = condition.size(); sql.append(" WHERE "); sql.append(con[0]); if (null != con[1] && con[1] != "" && con[1] != "useArg[0]") { sql.append(" " + con[1] + " ?"); } for (int i = 1; i < iLen; i++) { con = condition.get(i); sql.append(" AND "); sql.append(con[0]); if (null == con[1] || "" == con[1] || con[1] == "useArg[0]") continue; sql.append(" " + con[1] + " ?"); } } private void appendSetSql(StringBuffer sql, StringBuffer pql, List list, List obj) { for (Object[] arg : obj) { if (arg.length > 2) { sql.append(" " + arg[0] + " = " + arg[0] + arg[2] + " ?,"); pql.append(" " + arg[0] + " = " + arg[0] + arg[2] + arg[1] +","); list.add(arg[1]); }else if(arg.length == 2) { sql.append(" " + arg[0] + " = ?,"); pql.append(" " + arg[0] + " = " + arg[1] + ","); list.add(arg[1]); }else if(arg.length == 1) { sql.append(" " + arg[0] + ","); pql.append(" " + arg[0] + ","); } } } private String getTableSql(){ return (this._dbName == null || "".equals(this._dbName.trim()))? ("`"+this._tableName+"`"): ("`"+this._dbName+"`.`"+this._tableName+"`"); } private String constructUpdateSql(T entity, List beanFieldList) { StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"("); Iterator beanFieldIter = this._beanToTableField.keySet().iterator(); while(beanFieldIter.hasNext()){ String beanFieldName = beanFieldIter.next(); String tableFieldName = this._beanToTableField.get(beanFieldName); Field beanField = null; try { beanField = this._tClassInfo.getDeclaredField(beanFieldName); beanField.setAccessible(true); if(beanField.get(entity) == null) { continue; } } catch (Exception e) { continue; } if(tableFieldName == null || beanFieldName == null){ continue; } beanFieldList.add(beanField); sqlInsertPart.append("`"+tableFieldName+"`,"); } return sqlInsertPart.substring(0, sqlInsertPart.length()-1)+")"; } private Object getDefaultValueByFieldType(Field itemField) { String simpleName = itemField.getType().getSimpleName(); if("String".equals(simpleName)) { return ""; }else if("Date".equals(simpleName) || "Timestamp".equals(simpleName)) { return "2000-01-01 00:00:00"; }else if("BigDecimal".equals(simpleName)){ return BigDecimal.ZERO; }else { return 0; } } @Override public T findEntityByID(ID id) throws NotFoundException { return findEntityByID(id, false); } @Override public T findEntityByID(ID id, boolean isLock) throws NotFoundException { StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()); sql.append(" WHERE "+_idTableFieldName+" = ? "); if (isLock) { sql.append(" FOR UPDATE"); } try { return (T) _jdbcTemplateBroadcast.queryForObject(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, id); }catch (DataAccessException e) { throw new NotFoundException(e); } } @Override public T findEntityByCondition(List condition) throws NotFoundException, MultiRowException, NoContainTenantException { List tempList = findListByCondition(condition); if(tempList == null || tempList.size() == 0){ throw new NotFoundException(); } if(tempList != null && tempList.size() == 1){ return tempList.get(0); }else{ throw new MultiRowException(); } } @Override public T findEntityBySql(String sqlCondition) throws NotFoundException, MultiRowException { List tempList = findListBySql(sqlCondition); if(tempList == null || tempList.size() == 0){ throw new NotFoundException(); } if(tempList != null && tempList.size() == 1){ return tempList.get(0); }else{ throw new MultiRowException(); } } @Override public List findListByCondition(List condition){ return findListByCondition(condition, null); } @Override public List findListByCondition(List condition, String sortCondition){ StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()); List list = new ArrayList(); this.appendWhereCondition(sql, new StringBuffer(), list, condition); if(sortCondition != null && !sortCondition.equals("")){ sql.append(" " + sortCondition + " "); } return (List)_jdbcTemplateBroadcast.query(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, list.toArray()); } @Override public List findListBySql(String sqlCondition){ StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE " + sqlCondition); return (List)_jdbcTemplateBroadcast.query(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}); } @Override public Map findPageByCondition(List condition, int page, int pageSize){ return findPageByCondition(condition, null , page, pageSize); } @Override public Map findPageByCondition(List condition, String sortCondition, int page, int pageSize){ StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()); StringBuffer pql = new StringBuffer(sql.toString()); StringBuffer sqlCount = new StringBuffer("SELECT COUNT(1) rowCount FROM "+this.getTableSql()); List count_list = new ArrayList(); List page_list = new ArrayList(); this.appendWhereConditionForCount(sqlCount, condition); this.appendWhereCondition(sql, pql, count_list, condition); for (int i = 0; i < count_list.size(); i++) page_list.add(count_list.get(i)); page_list.add((page - 1) * pageSize); page_list.add(pageSize); if(sortCondition != null && !sortCondition.equals("")){ sql.append(" " + sortCondition + " "); pql.append(" " + sortCondition + " "); } String pageSql = sql.toString() + " limit ?, ?"; Map totalRowsMap = _jdbcTemplateBroadcast.queryForMap(sqlCount.toString(), new String[] {this._tableName}, count_list.toArray()) ; List resultList = _jdbcTemplateBroadcast.query(pageSql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, page_list.toArray()); return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList); } @Override public Map findPageBySql(String sqlCondition, int page, int pageSize){ StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE " + sqlCondition); StringBuffer sqlCount = new StringBuffer("SELECT count(1) rowCount FROM "+this.getTableSql()+" WHERE " + sqlCondition); sql.append(" limit ?, ?"); List page_list = new ArrayList(); page_list.add((page - 1) * pageSize); page_list.add(page * pageSize); Map totalRowsMap = _jdbcTemplateBroadcast.queryForMap(sqlCount.toString(), new String[] {this._tableName}); List resultList = _jdbcTemplateBroadcast.query(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, page_list.toArray()); return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList); } @Override public Number addEntity(T entity) { StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"("); StringBuffer sqlColumnPart = new StringBuffer(") VALUES ("); List paramList = new ArrayList(); Iterator beanFieldIter = this._beanToTableField.keySet().iterator(); while(beanFieldIter.hasNext()){ String beanFieldName = beanFieldIter.next(); String tableFieldName = this._beanToTableField.get(beanFieldName); Field beanField; Object beanFieldValue = null; try { beanField = this._tClassInfo.getDeclaredField(beanFieldName); beanField.setAccessible(true); beanFieldValue = beanField.get(entity); } catch (Exception e) { e.printStackTrace(); } if(tableFieldName == null || beanFieldName == null || beanFieldValue == null){ continue; } sqlInsertPart.append("`"+tableFieldName+"`,"); sqlColumnPart.append(" ?,"); paramList.add(beanFieldValue); } //执行SQL String exeSql = sqlInsertPart.substring(0, sqlInsertPart.length()-1)+sqlColumnPart.substring(0, sqlColumnPart.length()-1)+")"; KeyHolder _keyHolder = new GeneratedKeyHolder(new ArrayList>(1)); _jdbcTemplateBroadcast.update(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement(Connection con) throws SQLException { PreparedStatement stat = con.prepareStatement(exeSql, new String[] {_idTableFieldName}); PreparedStatementSetter setter = new ArgumentPreparedStatementSetter(paramList.toArray()); setter.setValues(stat); return stat; } }, _keyHolder, new String[] {this._tableName}); return _keyHolder.getKey(); } @Override public List addEntityList(List entityList) throws Exception { if(entityList == null || entityList.isEmpty()) { return Collections.EMPTY_LIST; } //构造SQL语句及Entity Field列表 List beanFieldList = new ArrayList(this._beanToTableField.size()); StringBuffer exeSql = new StringBuffer(this.constructUpdateSql(entityList.get(0), beanFieldList)); //构造参数信息 List args = new ArrayList(); exeSql.append(" VALUES"); for(int itemIndex=0; itemIndex>(entityList.size())); _jdbcTemplateBroadcast.update(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement(Connection con) throws SQLException { PreparedStatement stat = con.prepareStatement(exeSql.toString(), new String[] {_idTableFieldName}); PreparedStatementSetter setter = new ArgumentPreparedStatementSetter(args.toArray()); setter.setValues(stat); return stat; } }, _keyHolder, new String[] {this._tableName}); //处理结果数据 List> data = _keyHolder.getKeyList(); if(data.size() != entityList.size()) { throw new Exception("param entity size not equal return generate key list size"); } List dataT = new ArrayList(data.size()); for(Map item: data) { Iterator keyIter = item.values().iterator(); if (keyIter.hasNext()) { Object key = keyIter.next(); if (!(key instanceof Number)) { throw new DataRetrievalFailureException( "The generated key is not of a supported numeric type. " + "Unable to cast [" + (key != null ? key.getClass().getName() : null) + "] to [" + Number.class.getName() + "]"); } dataT.add((Number)key); }else { throw new DataRetrievalFailureException("Unable to retrieve the generated key. " + "Check that the table has an identity column enabled."); } } return dataT; } @Override public int deleteEntityByID(ID id) { StringBuffer sql = new StringBuffer("DELETE FROM "+this.getTableSql()+" WHERE"); sql.append(" "+this._idTableFieldName+" = ? "); return _jdbcTemplateBroadcast.update(sql.toString(), new String[] {this._tableName}, id); } @Override public int deleteEntityByCondition(List condition){ if (null == condition || condition.size() == 0) { throw new RuntimeException("params[condition] is empty"); } List list = new ArrayList(); StringBuffer sql = new StringBuffer("DELETE FROM "+this.getTableSql()+""); StringBuffer pql = new StringBuffer(sql.toString()); this.appendWhereCondition(sql, pql, list, condition); return _jdbcTemplateBroadcast.update( sql.toString(), new String[] {this._tableName}, list.toArray()); } @Override public int deleteEntityBySql(String sqlCondition){ if("".equals(sqlCondition.trim())) { throw new RuntimeException("params[sqlCondition] is empty"); } return _jdbcTemplateBroadcast.update( "DELETE FROM "+this.getTableSql()+" WHERE " + sqlCondition, new String[] {this._tableName}); } @Override public int deleteEntityList(List idList){ StringBuffer idSb = new StringBuffer(); for(ID id: idList) { idSb.append(id); } return this.deleteEntityBySql(this._idTableFieldName + " in ("+idSb.toString().substring(0, idSb.length()-1)+") "); } @Override public int updateEntityById(List changeList, ID id) { if(null == id){ throw new RuntimeException("params[id] is null"); } if (null == changeList || changeList.size() == 0) { throw new RuntimeException("params[changeList] is empty"); } StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET"); StringBuffer pql = new StringBuffer(sql.toString()); List list = new ArrayList(); this.appendSetSql(sql, pql, list, changeList); String where = " WHERE "+this._idTableFieldName+"=? "; String updateSql = sql.substring(0, sql.length()-1)+where; list.add(id); return _jdbcTemplateBroadcast.update(updateSql, new String[] {this._tableName}, list.toArray()); } @Override public int updateEntityByCondition(List updateObj, List condition){ if (null == updateObj || updateObj.size() == 0) { throw new RuntimeException("params[updateObj] is empty"); } if (null == condition || condition.size() == 0) { throw new RuntimeException("params[condition] is empty"); } StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET"); StringBuffer pql = new StringBuffer(sql.toString()); List list = new ArrayList(); this.appendSetSql(sql, pql, list, updateObj); StringBuffer where = new StringBuffer(""); StringBuffer pwhere = new StringBuffer(""); this.appendWhereCondition(where, pwhere, list, condition); String updateSql = sql.substring(0, sql.length()-1)+where.toString(); return _jdbcTemplateBroadcast.update(updateSql, new String[] {this._tableName}, list.toArray()); } @Override public int updateEntityBySql(List updateObj, String sqlCondition){ if (null == updateObj || updateObj.size() == 0) { throw new RuntimeException("params[updateObj] is empty"); } if ("".equals(sqlCondition)) { throw new RuntimeException("params[sqlCondition] is empty"); } StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET"); StringBuffer pql = new StringBuffer(sql.toString()); List list = new ArrayList(); this.appendSetSql(sql, pql, list, updateObj); String updateSql = sql.toString().substring(0, sql.length()-1) + " WHERE "+sqlCondition; return _jdbcTemplateBroadcast.update(updateSql, new String[] {this._tableName}, list.toArray()); } @Override public Map getPageData(String coreSql, String orderByPartSql, Integer page, Integer pageSize){ String[] splitedSql = UtilsSql.splitCoreSql(coreSql); return this.getPageData(splitedSql[0], splitedSql[1], orderByPartSql, page, pageSize); } @Override public Map getPageData(String selectSql, String fromAndWhereSql, String orderByPartSql, Integer page, Integer pageSize){ //构造查询语句 String querySql = selectSql+" "+fromAndWhereSql+" "+orderByPartSql+" "+UtilsSql.getLimitCondition(page, pageSize); //构造统计计数语句 String countSql = "select count(*) rowsCount from ( select 1 "+fromAndWhereSql+" ) t "; //执行查询 List> queryData = new ArrayList>(); Map countData = new HashMap(); queryData = this._jdbcTemplateBroadcast.queryForList(querySql, new String[] {this._tableName}); countData = this._jdbcTemplateBroadcast.queryForMap(countSql, new String[] {this._tableName}); return UtilsSql.createPage(page, pageSize, Integer.valueOf(countData.get("rowsCount").toString()), queryData); } }