MysqlUtil 5.3.1.3

package com.jfai.util;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.sql.DataSource;
/**
apache.commons.lang 工具包,可以在maven中添加如下依賴獲取
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>

 google的Gson工具包,可以在maven中添加如下依賴獲取
 <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
 <dependency>
 <groupId>com.google.code.gson</groupId>
 <artifactId>gson</artifactId>
 <version>2.8.5</version>
 </dependency>
  druid連接池包,可以在maven中添加如下依賴獲取
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>
 */
import org.apache.commons.lang.ArrayUtils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.sql.SQLUtils;
import com.google.gson.JsonObject;
import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;

import lombok.extern.slf4j.Slf4j;

/**
 * @author wanglf
 * @version 5.3.1.3
 * @Package com.jfai.kg.dao.impl
 * @Description: MysqlUtil
 * @date 2018年7月9日 上午10:52:04
 * @Attention
		 * 爲避免某些神奇的使用各種null做表名和參數的使用情況, 所以爲空校驗全部調爲Blank級別
		 * 關於參數非法的時候返回空對象還是null的問題,現在的策略是如果返回的對象是集合,則返回空的集合,其他則返回null(注:這樣主要是爲了調用的時候拿到集合返回對象,直接就可以遍歷,不用判斷null)
		 * 如果沒有規定明確要傳schemaName參數,tableName參數可以是 庫名.表名 的格式,從而對其他的庫進行操作
		 * mysql的bigint類型本身就包含了8個字節的長度,指定的長度只是指定顯示寬度,不影響存儲。所以無論是bigint(10),還是bigint(20)均佔用8個字節
 * @remark
		 * 修復表名``畫蛇添爪爪 問題 2018年7月19日21:09:44
		 * 增強並調整log顯示功能  2018年7月22日22:14:12
		 * 新增private方法,解除對StringUtil類方法的依賴 2018年7月26日16:00:40
		 * 增強並調整log顯示功能 2018年7月31日11:33:12
		 * 新增getBuildSQL方法 2018年7月31日12:12:21
		 * 新增execute方法 2018年7月31日12:28:02
		 * 新增getSchemas 獲取數據庫名的集合 功能 2018年7月31日14:05:11
		 * 新增List 插入 內包含批處理  2018年7月31日16:30:39
		 * 新增id相關的delete方法並更新註釋 2018年7月31日17:51:52
		 * 新增批量添加列功能列名修改功能和原新增列功能增強 2018年7月31日18:59:23
		 * 插入jsonOnbject的時候,新增忽略id功能(主要用來插入數據時目標表,有自己的主鍵生成策略的情況) 2018年8月3日19:32:39
		 * 新增依據id和idList查詢數據功能 2018年8月5日13:40:43
		 * 新增入口方法歡迎 2018年8月5日14:37:47
		 * 調整getTableInfo方法,新增列信息獲取方法  2018年8月7日09:55:25
		 * 新增isPrimaryKey和調整並增強getColumnInfo方法 2018年8月8日19:50:00
		 * 集成JDBCUtil的功能,新增關閉連接和資源的方法 2018年8月8日20:15:52
		 * 集成DataSourceSingleton,新增獲取數據源和獲取連接功能 2018年8月8日21:12:18
		 * 新增setParam方法,可以將有佔位符的SQL還原爲可執行的SQL 2018年8月11日19:23:25
 */
@Slf4j
public class MysqlUtil {
	private static DruidDataSource dataSource = new DruidDataSource();

	/**
	 * 私有化構造方法,工具類禁止new對象
	 */
	private MysqlUtil() {
	}

	/**
	 * 調用該方法可以返回一個mysql的數據源
	 * 目前使用的是阿里的Druid連接池
	 *
	 * @return
	 * @version 1.0.0
	 * @remark 也可以作爲單例模式的另一種實現, 因爲只New了一個DataSource
	 */
	public static DataSource getDataSource() {
		return dataSource;
	}

	/**
	 * 獲取數據庫連接
	 */
	public static Connection getConnection() {
		try {
			return dataSource.getConnection();
		} catch (SQLException e) {
			log.error("Exception :", e);
		}
		return null;
	}

	/**
	 * 初始化mysql數據庫,優化mysql數據庫設置
	 *
	 * @version 1.0.0
	 * @Description 設置mysql的最大併發連接數爲5000
	 * 設置mysql的緩衝中間表的size=256M
	 * 設置mysql緩衝區大小=32M
	 * 設置mysql允許接收的的最大數據包尺寸爲16M
	 * @remark 可能涉及了一點mysql的數據庫調優
	 */
	public static void init() {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		long t1 = System.currentTimeMillis();
		Connection conn = null;
		Statement stm = null;
		ResultSet rs = null;

		// 設置mysql的最大併發連接數爲5000,併發連接數設小了,坑.. 雖然一般用不到5000
		String sql = "set GLOBAL max_connections =5000";

		// 設置mysql的緩衝中間表的size,不然涉及列操作的時候,可能會出現二次讀寫,特別是百萬數據大表,那速度 ...
		String sql_1 = "set GLOBAL tmp_table_size =256*1024*1024";// -- 256M
		// 設置mysql緩衝區大小
		String sql_2 = "set GLOBAL read_buffer_size =32*1024*1024";// -- 32M
		// 設置mysql允許的最大的一次可允許接收數據量,不然大數據量批處理操作,你懂得 ..
		String sql_3 = "set GLOBAL max_allowed_packet = 16*1024*1024";// -- 16M

		try {
			conn = dataSource.getConnection();
			conn.setAutoCommit(false);

			stm = conn.createStatement();
			stm.addBatch(sql);
			stm.addBatch(sql_1);
			stm.addBatch(sql_2);
			stm.addBatch(sql_3);

			stm.executeBatch();
			conn.commit();// 執行完後,手動提交事務,不然會回滾
			conn.setAutoCommit(true);// 再把自動提交打開
			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.init>>執行SQL完畢!, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
		} catch (Exception e) {
			try {
				conn.rollback();
				log.error("MysqlUtil.init log error!", e);
			} catch (SQLException e1) {
				log.error("Exception :", e1);
			}
		} finally {
			close(rs, stm, conn);
		}
	}

	/**
	 * 關閉相關資源,並返回連接
	 *
	 * @param rs         java.sql.ResultSet 數據庫結果集
	 * @param s          java.sql.Statement SQL執行體
	 * @param connection java.sql.Connection  數據庫連接
	 * @version 1.0.0
	 */
	public static void close(ResultSet rs, Statement s, Connection connection) {
		clostResultSet(rs);
		clostStatement(s);
		clostConnection(connection);
	}

	/**
	 * 關閉ResultSet
	 *
	 * @param rs java.sql.ResultSet
	 * @version 1.0.0
	 * @Attention
	 */
	public static void clostResultSet(ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
			} catch (Exception e) {
				log.error("Exception :", e);
			}
		}
	}

	/**
	 * 關閉Statement 注:PreparedStatement也可以用該方法關閉
	 *
	 * @param s java.sql.Statement
	 * @version 1.0.0
	 * @remark PreparedStatement是Statement的子類, 所以也可以使用該方法關閉
	 */
	public static void clostStatement(Statement s) {
		if (s != null) {
			try {
				s.close();
			} catch (Exception e) {
				log.error("Exception :", e);
			}
		}
	}

	/**
	 * 返回連接到連接池,如果未使用連接池,則會直接關閉連接
	 *
	 * @param conn
	 * @version 1.0.0
	 * @Attention 如果未使用連接池, 則會直接關閉連接
	 * 如果使用連接池,會將連接返回連接池
	 */
	public static void clostConnection(Connection conn) {
		if (conn != null) {
			try {
				conn.close();
			} catch (Exception e) {
				log.error("Exception :", e);
			}
		}
	}

	/**
	 * 向指定的表插入數據,數據類型爲map 的key-value形式
	 *
	 * @param dataMap   要插入的數據集
	 * @param tableName 表名
	 * @return true or false
	 */
	public static boolean add(Map<String, Object> dataMap, String tableName) {
		return insert(dataMap, tableName);
	}

	/**
	 * 向指定的表插入數據,數據類型爲map 的key-value形式
	 *
	 * @param dataMap   要插入的數據集
	 * @param tableName 表名
	 * @return true or false
	 */
	public static boolean insert(Map<String, Object> dataMap, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (tableName == null || tableName.length() == 0) {
			log.error("MysqlUtil.insert Parameter[tableName] is empty ! Return!");
			return false;
		}
		if (dataMap == null || dataMap.size() == 0) {
			log.error("MysqlUtil.insert Parameter[dataMap] is empty ! Return!");
			return false;
		}

		long t1 = System.currentTimeMillis();

		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;

		StringBuilder sql = new StringBuilder();
		StringBuilder p = new StringBuilder();
//		Object[] args = new Object[dataMap.size()];
		sql.append("insert into  " + tableName + "( ");
//		int i = 0;
//		for (String aName : dataMap.keySet()) {
//			if (i != dataMap.size() - 1) {
//				sql.append(aName + ",");
//				p.append("?,");
//			} else {
//				sql.append(aName);
//				p.append("?");
//			}
//			args[i] = dataMap.get(aName);
//			i++;
//		}
//		sql.append(") values(").append(p).append(")");
		
		List<Object> params =new LinkedList<Object>();
		for (String aName : dataMap.keySet()) {
			sql.append(aName + ",");
			p.append("?,");
			params.add(dataMap.get(aName));
		}
		sql.deleteCharAt(sql.length()-1).append(") values(").append(p.deleteCharAt(p.length()-1)).append(")");
		
		int re = 0;
		try {
			conn = dataSource.getConnection();
			
			sql=new StringBuilder((setParam(params, sql.toString())));
			
			pstm = conn.prepareStatement(sql.toString());
//			for (int k = 0; k < args.length; k++) {
//				pstm.setObject(k + 1, args[k]);
//			}

			re = pstm.executeUpdate();
			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.insert>>執行SQL: {}, 耗時: {}ms", sql.toString(), t2 - t1);
			//log.info("MysqlUtil.insert>>傳入的參數值arg=>{}", Arrays.toString(args));
		} catch (Exception e) {
			log.error("MysqlUtil.insert>>執行SQL: {}", sql);
			//log.error("MysqlUtil.insert>>傳入的參數值arg=>{}", Arrays.toString(args));
			log.error("MysqlUtil.insert log error!", e);
		} finally {
			close(rs, pstm, conn);
		}
		return re == 0 ? false : true;
	}

	/**
	 * @param dataMap   要更改的值map
	 * @param condition where條件值  key-value形式,用map包裝
	 * @param tableName 表名  可以爲庫名.表名形式
	 * @return true or false
	 */
	public static boolean update(Map<String, Object> dataMap, Map<String, Object> condition, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (tableName == null || tableName.length() == 0) {
			log.error("MysqlUtil.update Parameter[tableName] is empty ! Return!");
			return false;
		}
		if (dataMap == null || dataMap.size() == 0) {
			log.error("MysqlUtil.update Parameter[dataMap] is empty ! Return!");
			return false;
		}

		if (condition == null || condition.size() == 0) {
			log.error("MysqlUtil.update Parameter[condition] is empty ! Return!");
			return false;
		}

		long t1 = System.currentTimeMillis();

		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;

		StringBuilder sql = new StringBuilder();
		Object[] arg1 = new Object[dataMap.size()];
		Object[] arg2 = new Object[condition.size()];

		sql.append("update " + tableName + " set ");
		int i = 0;
		for (String aName : dataMap.keySet()) {
			if (i != dataMap.size() - 1) {
				sql.append("`" + aName + "` = ? ,");
			} else {
				sql.append("`" + aName + "` = ?  where ");
			}
			arg1[i] = dataMap.get(aName);
			i++;
		}

		int j = 0;
		for (String cName : condition.keySet()) {
			if (j != condition.size() - 1) {
				sql.append("`" + cName + "` = ? ,");
			} else {
				sql.append("`" + cName + "` = ?");
			}
			arg2[j] = condition.get(cName);
			j++;
		}

		Object[] args = ArrayUtils.addAll(arg1, arg2);

		int re = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql.toString());
			for (int k = 0; k < args.length; k++) {
				pstm.setObject(k + 1, args[k]);
			}
			re = pstm.executeUpdate();
			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.update>>執行SQL: {}, 耗時: {}ms", sql.toString(), t2 - t1);
			log.info("MysqlUtil.update>>傳入的參數值arg=>{}", Arrays.toString(args));
			if (re != 0) {
				log.info("MysqlUtil.update successfully !");
				return true;
			}
		} catch (Exception e) {
			log.error("MysqlUtil.update>>執行SQL: {}", sql);
			log.error("MysqlUtil.update>>傳入的參數值arg=>{}", Arrays.toString(args));
			log.error("MysqlUtil.update log error!", e);
		} finally {
			close(rs, pstm, conn);
		}
		return re == 0 ? false : true;
	}

	/**
	 * 依據condition刪除數據
	 *
	 * @param condition Map<String, Object>形式,可以包含多條key value
	 * @param tableName
	 * @return true or false
	 */
	public static boolean delete(Map<String, Object> condition, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (tableName == null || tableName.length() == 0) {
			log.error("MysqlUtil.delete Parameter[tableName] is empty ! Return!");
			return false;
		}
		if (condition == null || condition.size() == 0) {
			log.error("MysqlUtil.delete Parameter[condition] is empty !  Return !");
			return false;
		}
		long t1 = System.currentTimeMillis();

		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;

		StringBuilder sql = new StringBuilder();
		Object[] args = new Object[condition.size()];
		sql.append("delete from " + tableName + " where ");
		int i = 0;
		for (String cName : condition.keySet()) {
			if (i != condition.size() - 1) {
				sql.append("`" + cName + "` = ? ,");
			} else {
				sql.append("`" + cName + "` = ?");
			}
			args[i] = condition.get(cName);
			i++;
		}

		int re = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql.toString());
			for (int k = 0; k < args.length; k++) {
				pstm.setObject(k + 1, args[k]);
			}
			re = pstm.executeUpdate();
			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.delete>>執行SQL: {}, 耗時: {}ms", sql.toString(), t2 - t1);
			log.info("MysqlUtil.delete>>傳入的參數值arg=>{}", Arrays.toString(args));
			if (re != 0) {
				log.info("MysqlUtil.delete successfully !");
				return true;
			}
		} catch (Exception e) {
			log.error("MysqlUtil.delete>>執行SQL: {}", sql);
			log.error("MysqlUtil.delete>>傳入的參數值arg=>{}", Arrays.toString(args));
			log.error("MysqlUtil.delete log error!", e);
		} finally {
			close(rs, pstm, conn);
		}

		return re == 0 ? false : true;

	}

	/**
	 * 依據id刪除數據
	 *
	 * @param id
	 * @param tableName
	 * @return true or false
	 */
	public static boolean deleteById(Object id, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (tableName == null || tableName.length() == 0) {
			log.error("MysqlUtil.deleteById Parameter[tableName] is empty ! Return!");
			return false;
		}
		if (id == null || String.valueOf(id).length() == 0) {
			log.error("MysqlUtil.deleteById Parameter[id] is empty !  Return !");
			return false;
		}
		long t1 = System.currentTimeMillis();

		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;

		String sql = "delete from " + tableName + " where id = ?";

		int re = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			pstm.setObject(1, id);
			re = pstm.executeUpdate();
			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.deleteById>>執行SQL: {}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
			log.info("MysqlUtil.deleteById>>傳入的參數值arg=>id:{},tableName:{}", String.valueOf(id), tableName);
			if (re != 0) {
				log.info("MysqlUtil.deleteById successfully !");
				return true;
			}
		} catch (Exception e) {
			log.error("MysqlUtil.deleteById>>執行SQL: {}", sql);
			log.error("MysqlUtil.deleteById>>傳入的參數值arg=>id:{},tableName:{}", String.valueOf(id), tableName);
			log.error("MysqlUtil.deleteById log error!", e);
		} finally {
			close(rs, pstm, conn);
		}
		return re == 0 ? false : true;
	}

	/**
	 * 執行指定的SQL,返回受影響的行數
	 *
	 * @param sql
	 * @return 受影響的行數
	 */
	public static int execute(String sql) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (isBlank(sql)) {
			log.error("MysqlUtil.execute Parameter[sql:{}] is empty !  Return !", sql);
			return 0;
		}
		long t1 = System.currentTimeMillis();

		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;

		int re = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			re = pstm.executeUpdate();
			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.execute>>執行SQL: {}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
		} catch (Exception e) {
			log.error("MysqlUtil.execute>>執行SQL: {}", sql);
			log.error("MysqlUtil.execute log error!", e);
		} finally {
			close(rs, pstm, conn);
		}
		return re;
	}

	/**
	 * execute 方法可以傳參,注意參數的順序
	 *
	 * @param sql
	 * @param args
	 * @return
	 */
	public static int execute(String sql, Object... args) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (isBlank(sql)) {
			log.error("MysqlUtil.execute Parameter[sql] is empty !  Return !");
			return 0;
		}
		long t1 = System.currentTimeMillis();

		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;

		int re = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			for (int k = 0; k < args.length; k++) {
				pstm.setObject(k + 1, args[k]);
			}
			re = pstm.executeUpdate();
			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.execute>>執行SQL: {}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
			log.info("MysqlUtil.execute>>傳入的參數值arg=>{}", Arrays.toString(args));
		} catch (Exception e) {
			log.error("MysqlUtil.execute>>執行SQL: {}", sql);
			log.error("MysqlUtil.execute>>傳入的參數值arg=>{}", Arrays.toString(args));
			log.error("MysqlUtil.execute log error!", e);
		} finally {
			close(rs, pstm, conn);
		}

		return re;
	}

	/**
	 * 獲取數據庫名集合
	 *
	 * @return List<String> 數據庫名集合
	 */
	public static List<String> getSchemas() {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		long t1 = System.currentTimeMillis();
		String sql = "SHOW DATABASES";
		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		List<String> list = new ArrayList<String>();
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			rs = pstm.executeQuery();
			while (rs.next()) {
				list.add(rs.getString("Database"));
			}
			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.getSchemas>>執行SQL: {}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
			if (list.size() != 0) {
			}
		} catch (Exception e) {
			log.error("MysqlUtil.getSchemas>>執行SQL: {}", sql);
			log.error("MysqlUtil.getSchemas log error! errorMsg:", e);
		} finally {
			close(rs, pstm, conn);
		}
		return list;
	}

	/**
	 * 依據數據庫名查詢,查詢該庫的數據表列表
	 *
	 * @param databaseName 數據庫名
	 * @return List<String> 表名集合
	 */
	public static List<String> getTables(String databaseName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (isNull(databaseName)) {
			log.info("MysqlUtil.getTables => The key parameter[databaseName:{}] is empty and returns directly", databaseName);
			return null;
		}
		long t1 = System.currentTimeMillis();
		String sql = "SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA= ?";
		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		List<String> list = new ArrayList<String>();
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			pstm.setString(1, databaseName);
			rs = pstm.executeQuery();
			while (rs.next()) {
				list.add(rs.getString("TABLE_NAME"));
			}

			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.getTables>>執行SQL: {}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
			log.info("MysqlUtil.getTables>>傳入的參數值databaseName:{}", databaseName);
			if (list.size() != 0) {
				log.info("MysqlUtil.getTables=> select succeeded!", databaseName);
			}
		} catch (Exception e) {
			log.error("MysqlUtil.getTables>>執行SQL: {}", sql);
			log.error("MysqlUtil.getTables>>傳入的參數值databaseName:{}", databaseName);
			log.error("MysqlUtil.getTables log error! errorMsg:", e);
		} finally {
			close(rs, pstm, conn);
		}

		return list;
	}

	/**
	 * 獲取表信息,返回包含表列信息的map
	 *
	 * @param tableName 允許爲庫名.表名格式,查詢其它庫的表信息
	 * @return 包含目標表列信息的map
	 * @Attention 注意表不存在的時候會返回null
	 */
	public static Map<String, String> getTableInfo(String tableName) {
		return getTableInfo2(null, tableName);
	}

	/**
	 * 直接查詢mysql information_s 信息表獲得目標表的列信息,效率會比getTableInfo desc語句執行效率高.
	 * 返回包含目標表列信息的map,key爲列名,value爲列類型,注:在目標庫中,目標表不存在時會返回null
	 *
	 * @param schemaName 庫名
	 * @param tableName  表名
	 * @return 包含目標表列信息的map或null, 注:key爲列名,value爲列類型,表不存在時,返回null
	 * @version 1.0.0
	 * @Attention 該函數tableName參數也可以支持庫名.表名的格式, 但不推薦這樣做!如果這樣,傳參數請將schemaName設置爲""或null
	 */
	public static Map<String, String> getTableInfo(String schemaName, String tableName) {
		if (isNull(tableName)) {
			log.info("MysqlUtil.getTableInfo2 => The key parameter[tableName:{}] is empty and returns directly", tableName);
			return null;
		}
		if (isNull(schemaName)) {
			String[] split = tableName.split("\\.");
			if (split.length == 1) {
				log.info("MysqlUtil.getTableInfo2 => The key parameter[schemaName:{}] is empty and returns directly", schemaName);
				return null;
			} else if (split.length == 2) {
				schemaName = split[1];
				tableName = split[2];
			} else {
				log.info("MysqlUtil.getTableInfo2 => The key parameter[tableName:{}] is illegal and returns directly", tableName);
				return null;
			}
		}

		long t1 = System.currentTimeMillis();
		String sql = "SELECT COLUMN_NAME,COLUMN_TYPE FROM information_schema.COLUMNS WHERE `TABLE_SCHEMA`='" + schemaName + "' AND `TABLE_NAME`= ?";
		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		Map<String, String> tableColInfo = new LinkedHashMap<String, String>();
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			pstm.setString(1, tableName);
			rs = pstm.executeQuery();
			while (rs.next()) {
				String columnName = rs.getString("COLUMN_NAME");
				String columnType = rs.getString("COLUMN_TYPE");
				tableColInfo.put(columnName, columnType);
			}
			long t2 = System.currentTimeMillis();
			log.info(">>執行SQL:{}, 耗時: {}ms", sql.toString(), t2 - t1);
			log.info(">>傳入的參數值tableName:{}", tableName);
			if (tableColInfo.size() != 0) {
				log.info(">> getTableInfo successfully! tableColInfo.size:{}", tableColInfo.size());
			} else {
				return null;
			}
		} catch (Exception e) {
			log.error(">>執行SQL: {}", sql.toString());
			log.error(">>傳入的參數值tableName:{}", tableName);
			log.error(" getTableInfo log error! errorMsg:", e);
			return null;
		} finally {
			close(rs, pstm, conn);
		}
		return tableColInfo;
	}

	/**
	 * 獲取包含目標表列信息的map,key爲列名,value爲列類型
	 *
	 * @param schemaName 庫名
	 * @param tableName  表名
	 * @return 包含目標表列信息的map, 注:key爲列名,value爲列類型
	 * @version 1.0.0
	 * @Attention 注意表不存在的時候會返回null
	 */
	public static Map<String, String> getTableInfo2(String schemaName, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (isNull(tableName)) {
			log.info("MysqlUtil.getTableInfo => The key parameter[tableName:{}] is empty and returns directly", tableName);
			return null;
		}
		if (isNotBlank(schemaName)) {
			tableName = schemaName + "." + tableName;
		}
		long t1 = System.currentTimeMillis();
		String sql = "desc " + tableName;
		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		Map<String, String> tableColInfo = new LinkedHashMap<String, String>();
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			rs = pstm.executeQuery();
			while (rs.next()) {
				tableColInfo.put(rs.getString("Field"), rs.getString("Type"));
			}

			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.getTableInfo>>執行SQL: {}, 耗時: {}ms", sql.toString(), t2 - t1);
			log.info("MysqlUtil.getTableInfo>>傳入的參數值tableName:{}", tableName);

			if (tableColInfo.size() != 0) {
				log.info("MysqlUtil.getTableInfo>>getTableInfo successfully! ");
			} else {
				return null;
			}
		} catch (Exception e) {
			log.error("MysqlUtil.getTableInfo>>執行SQL: {}", sql.toString());
			log.error("MysqlUtil.getTableInfo>>傳入的參數值tableName:{}", tableName);
			log.error("MysqlUtil.getTableInfo log error! errorMsg:", e);
			// 如果查不到表信息代表這一張表不存在,直接返回null
			return null;
		} finally {
			close(rs, pstm, conn);
		}

		return tableColInfo;
	}

	/**
	 * 獲取表的建表語句
	 *
	 * @param tableName 表名 可以爲庫名.表名形式
	 * @return BuildSQL or null
	 */
	public static String getBuildSQL(String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (isNull(tableName)) {
			log.info("MysqlUtil.getBuildSQL => The key parameter[tableName:{}] is empty and returns directly", tableName);
			return null;
		}
		long t1 = System.currentTimeMillis();
		String sql = "SHOW CREATE TABLE " + tableName;
		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		String createTableSQL = null;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			rs = pstm.executeQuery();
			if (rs.next()) {
				createTableSQL = rs.getString("Create Table");
				long t2 = System.currentTimeMillis();
				log.info("MysqlUtil.getBuildSQL>>執行SQL:{}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
				log.info("MysqlUtil.getBuildSQL>>傳入的參數值tableName:{}", tableName);
				log.info("MysqlUtil.getBuildSQL successfully! createTableSQL.length:{}", createTableSQL.length());
				return createTableSQL.length() == 0 ? null : createTableSQL;
			}
		} catch (Exception e) {
			log.error("MysqlUtil.getBuildSQL>>執行SQL: {}", sql);
			log.error("MysqlUtil.getBuildSQL>>傳入的參數值tableName:{}", tableName);
			log.error("MysqlUtil.getBuildSQL log error! errorMsg:", e);
			return null;
		} finally {
			close(rs, pstm, conn);
		}
		return createTableSQL;
	}

	/**
	 * 格式化SQL語句
	 *
	 * @Attention 注意是MySQL家的SQL語句
	 */
	public static String formatSQL(String sql) {
		return SQLUtils.formatMySql(sql);
	}

	/**
	 * 格式化SQL語句
	 *
	 * @Attention 注意是MySQL家的SQL語句
	 */
	public static String getFormatSQL(String sql) {
		return SQLUtils.formatMySql(sql);
	}

	/**
	 * 獲取目標列的詳細信息
	 *
	 * @param columnName 列名
	 * @param tableName  表名
	 * @param schemaName 庫名
	 * @return 包含查詢列詳細信息的map或null 注:當目標列信息不存在是返回null
	 * COLUMN_TYPE 列類型,注意有可能是bigint(20) unsigned的返回值
	 * DATA_TYPE 數據類型,如:bigint
	 * DATA_LENGTH 列長度
	 * ORDINAL_POSITION 該列位於所在表的第幾列
	 * IS_NULLABLE 是否可以爲空
	 * EXTRA 額外信息,如auto_increment
	 * COLUMN_NAME 列名
	 * TABLE_NAME 該列所在的表名
	 * TABLE_SCHEMA 該列所在的表的庫名
	 * @version 1.0.0
	 * @Attention 目標列信息不存在是返回null
	 */
	public static Map<String, String> getColumnInfo(String columnName, String tableName, String schemaName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (isNull(columnName)) {
			log.info("MysqlUtil.getColumnInfo => The key parameter[columnName:{}] is empty and returns directly", columnName);
			return null;
		}
		if (isNull(tableName)) {
			log.info("MysqlUtil.getColumnInfo => The key parameter[tableName:{}] is empty and returns directly", tableName);
			return null;
		}
		if (isNull(schemaName)) {
			log.info("MysqlUtil.getColumnInfo => The key parameter[schemaName:{}] is empty and returns directly", schemaName);
			return null;
		}

		long t1 = System.currentTimeMillis();
		String sql = "SELECT COLUMN_TYPE,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,ORDINAL_POSITION ,IS_NULLABLE,EXTRA,COLUMN_NAME,TABLE_NAME,TABLE_SCHEMA FROM information_schema.COLUMNS " + " WHERE `TABLE_SCHEMA`='" + schemaName + "' AND `TABLE_NAME`= '" + tableName + "' AND `COLUMN_NAME`= '" + columnName
				+ "'";
		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		Map<String, String> columnInfo = new LinkedHashMap<String, String>();
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			rs = pstm.executeQuery();
			if (rs.next()) {
				columnInfo.put("COLUMN_TYPE", rs.getString("COLUMN_TYPE"));// COLUMN_TYPE 中可能包含unsigned或signed的信息如:bigint(20) unsigned
				columnInfo.put("DATA_TYPE", rs.getString("DATA_TYPE"));
				String DATA_LENGTH = rs.getString("CHARACTER_MAXIMUM_LENGTH");
				if (DATA_LENGTH == null) {
					DATA_LENGTH = rs.getString("NUMERIC_PRECISION");
				}
				columnInfo.put("DATA_LENGTH", DATA_LENGTH);
				columnInfo.put("ORDINAL_POSITION", rs.getString("ORDINAL_POSITION"));
				columnInfo.put("IS_NULLABLE", rs.getString("IS_NULLABLE"));
				columnInfo.put("EXTRA", rs.getString("EXTRA")); // EXTRA 中會包含是否 自增 等信息 auto_increment
				columnInfo.put("COLUMN_NAME", rs.getString("COLUMN_NAME"));
				columnInfo.put("TABLE_NAME", rs.getString("TABLE_NAME"));
				columnInfo.put("TABLE_SCHEMA", rs.getString("TABLE_SCHEMA"));
			}
			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.getColumnInfo>>執行SQL:{}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
			log.info("MysqlUtil.getColumnInfo>>傳入的參數值columnName:{},tableName:{},schemaName:{}", columnName, tableName, schemaName);
			if (columnInfo.size() != 0) {
				log.info("MysqlUtil.getColumnInfo successfully! columnInfo:{}", columnInfo.toString());
				return columnInfo;
			} else {
				log.info("MysqlUtil.getColumnInfo failure! columnInfo is empty!columnInfo.size:{}", columnInfo.size());
				return null;
			}
		} catch (Exception e) {
			log.error("MysqlUtil.getColumnInfo>>執行SQL: {}", sql);
			log.error("MysqlUtil.getColumnInfo>>傳入的參數值columnName:{},tableName:{},schemaName:{}", columnName, tableName, schemaName);
			log.error("MysqlUtil.getColumnInfo log error! errorMsg:", e);
			return null;
		} finally {
			close(rs, pstm, conn);
		}
	}

	/**
	 * 查詢目標列的是否是主鍵
	 *
	 * @param columnName 目標列列名
	 * @param tableName  目標列所在的表名
	 * @param schemaName 目標列所在的庫名
	 * @return true or false 目標列是否是其所在表的主鍵
	 * @version 1.0.0
	 */
	public static boolean isPrimaryKey(String columnName, String tableName, String schemaName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (isNull(columnName)) {
			log.info("MysqlUtil.isPrimaryKey => The key parameter[columnName:{}] is empty and returns directly", columnName);
			return false;
		}
		if (isNull(tableName)) {
			log.info("MysqlUtil.isPrimaryKey => The key parameter[tableName:{}] is empty and returns directly", tableName);
			return false;
		}
		if (isNull(schemaName)) {
			log.info("MysqlUtil.isPrimaryKey => The key parameter[schemaName:{}] is empty and returns directly", schemaName);
			return false;
		}

		long t1 = System.currentTimeMillis();
		String sql = "SELECT CONSTRAINT_NAME FROM information_schema.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA`='" + schemaName + "' AND `TABLE_NAME`= '" + tableName + "' AND `COLUMN_NAME`= '" + columnName + "' ";
		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			rs = pstm.executeQuery();

			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.isPrimaryKey>>執行SQL:{}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
			log.info("MysqlUtil.isPrimaryKey>>傳入的參數值columnName:{},tableName:{},schemaName:{}", columnName, tableName, schemaName);
			if (rs.next()) {
				return "PRIMARY".equals(rs.getString("CONSTRAINT_NAME"));
			} else {
				return false;
			}
		} catch (Exception e) {
			log.error("MysqlUtil.isPrimaryKey>>執行SQL: {}", sql);
			log.error("MysqlUtil.isPrimaryKey>>傳入的參數值columnName:{},tableName:{},schemaName:{}", columnName, tableName, schemaName);
			log.error("MysqlUtil.isPrimaryKey log error! errorMsg:", e);
			return false;
		} finally {
			close(rs, pstm, conn);
		}
	}

	/**
	 * 依據表名和where條件進行數據統計
	 */
	public static Integer getDataStat(String tableName, String where) {
		return getCount(tableName, where);
	}

	/**
	 * 依據表名和where條件進行行數統計 ,where 條件可以爲空或null,句首可以不爲空格
	 *
	 * @param tableName
	 * @param where     相關的條件語句可以爲空,如果不爲空,則必須要有where關鍵詞,但where關鍵詞前可以不加空格
	 * @return 統計的數據總量
	 * @remark: statistic 統計學 statistical 統計的
	 */
	public static Integer getCount(String tableName, String where) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (isNull(tableName)) {
			log.info("MysqlUtil.getCount => The key parameter[tableName:{}] is empty and returns directly", tableName);
			return null;
		}
		long t1 = System.currentTimeMillis();
		String sql = "select count(1) as num from " + tableName + " ";
		if (isNotNull(where)) {
			sql += where;
		}

		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		Integer re = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			rs = pstm.executeQuery();
			if (rs.next()) {
				re = rs.getInt("num");
				long t2 = System.currentTimeMillis();
				log.info("MysqlUtil.getCount>>執行SQL: {}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
				log.info("MysqlUtil.getCount>>傳入的參數值tableName:{}", tableName);
				log.info("MysqlUtil.getCount=> Table:{} get statistics info succeeded! num:{}", tableName, re);
			}
		} catch (Exception e) {
			log.error("MysqlUtil.getCount>>執行SQL: {}", sql);
			log.error("MysqlUtil.getCount>>傳入的參數值tableName:{}", tableName);
			log.error("MysqlUtil.getCount log error! errorMsg:", e);
		} finally {
			close(rs, pstm, conn);
		}

		return re;
	}

	/**
	 * 依據表名返回List<JsonObject> 全查詢結果集,可以附:where條件和limit參數
	 *
	 * @param tableName
	 * @param where      注意查詢條件要加where關鍵詞 , 可以爲null或""
	 * @param limitStart 可以爲null
	 * @param getCount   可以爲null
	 * @return List<JsonObject> 查詢到的數據集合 可能返回空list集合,但不返回null
	 */
	public static List<JsonObject> getData(String tableName, String where, Integer limitStart, Integer getCount) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		List<JsonObject> list = new ArrayList<JsonObject>();
		if (isNull(tableName)) {
			log.info("MysqlUtil.getData => The key parameter[tableName:{}] is empty and returns directly", tableName);
			return list;
		}
		long t1 = System.currentTimeMillis();
		String sql = "select * from " + tableName + " ";
		if (isNotNull(where)) {
			sql += where;
		}
		if (limitStart != null && getCount != null) {
			sql += " limit " + limitStart + "," + getCount + " ";
		}
		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			rs = pstm.executeQuery();
			list = GsonUtil.resultSetToJsonObjList(rs);
			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.getData>>執行SQL: {}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
			log.info("MysqlUtil.getData>>傳入的參數值tableName:{}", tableName);
			log.info("MysqlUtil.getData=> Table:{} getData succeeded! list.size:{}", tableName, list.size());

			return list;
		} catch (Exception e) {
			log.error("MysqlUtil.getData>>執行SQL: {}", sql);
			log.error("MysqlUtil.getData>>傳入的參數值tableName:{}", tableName);
			log.error("MysqlUtil.getData log error! errorMsg:", e);
			return list;
		} finally {
			close(rs, pstm, conn);
		}
	}

	/**
	 * 依據表名和id返回該行的JsonObject數據,注意:傳入的id參數對應的列名就是id
	 *
	 * @param id        該行數據的id值
	 * @param tableName 要查詢的表名
	 * @return 該id對應行的JsonObject數據
	 * @Attention 傳入的id參數對應的列名就是id
	 */
	public static JsonObject getData(Object id, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (isBlank(tableName)) {
			log.info("MysqlUtil.getData => The key parameter[tableName:{}] is empty , return directly!", tableName);
			return null;
		}
		if (id == null) {
			log.info("MysqlUtil.getData => The key parameter[id] is null , return directly!");
			return null;
		}
		long t1 = System.currentTimeMillis();
		String sql = "select * from " + tableName + " where id = ?";

		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			pstm.setObject(1, id);
			rs = pstm.executeQuery();
			JsonObject jsonObject = GsonUtil.resultSetToJsonObject(rs);

			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.getData>>執行SQL: {}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
			log.info("MysqlUtil.getData>>傳入的參數值id:{},tableName:{}", GsonUtil.toJson(id), tableName);
			log.info("MysqlUtil.getData=> Table:{} getData succeeded! data:{}", tableName, jsonObject.toString());

			return jsonObject;
		} catch (Exception e) {
			log.error("MysqlUtil.getData>>執行SQL: {}", sql);
			log.error("MysqlUtil.getData>>傳入的參數值tableName:{}", tableName);
			log.error("MysqlUtil.getData log error! errorMsg:", e);
			return null;
		} finally {
			close(rs, pstm, conn);
		}
	}

	/**
	 * 依據傳入的idList查詢相應的數據,返回ArrayList<JsonObject>
	 *
	 * @param ids       傳入的idList集合
	 * @param tableName 表名
	 * @return ArrayList<JsonObject>數據集合
	 */
	public static List<JsonObject> getData(List<Object> ids, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		List<JsonObject> list = new ArrayList<JsonObject>();
		if (isBlank(tableName)) {
			log.info("MysqlUtil.getData => The key parameter[tableName:{}] is empty , return directly!", tableName);
			return list;
		}
		if (ids == null || ids.isEmpty()) {
			log.info("MysqlUtil.getData => The key parameter[ids] is empty , return directly!");
			return list;
		}

		for (Object id : ids) {
			JsonObject data = getData(id, tableName);
			if (data != null) {
				list.add(data);
			}
		}
		return list;
	}

	/**
	 * 爲 表添加一列 ,默認爲varchar類型
	 *
	 * @param colName   列名
	 * @param colLen    列長度
	 * @param tableName 表名
	 * @return 返回受影響的列數
	 */
	public static int addCol(String colName, int colLen, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		long t1 = System.currentTimeMillis();
		String sql = "alter table " + tableName + " add column `" + colName + "` varchar(" + colLen + ") default null ";
		Connection conn = null;
		PreparedStatement pstm = null;
		int i = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			i = pstm.executeUpdate();

			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.addCol>>執行SQL: {}, 耗時: {}ms", sql, t2 - t1);
			log.info("MysqlUtil.addCol>>傳入的參數值tableName:{},colName:{}", tableName, colName);
			log.info("MysqlUtil.addCol => added column succeeded!");
		} catch (Exception e) {
			log.error("MysqlUtil.addCol>>執行SQL: {}", sql);
			log.error("MysqlUtil.addCol>>傳入的參數值tableName:{},colLen:{},colName:{}", tableName, colLen, colName);
			log.error("MysqlUtil.addCol log error! errorMsg:", e);
		} finally {
			close(null, pstm, conn);
		}
		return i;
	}

	/**
	 * 爲 表添加一列 ,默認爲varchar類型
	 *
	 * @param colName   列名
	 * @param colType   列類型 如 int(10)
	 * @param tableName 表名
	 * @return 返回受影響的列數
	 */
	public static int addCol(String colName, String colType, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		long t1 = System.currentTimeMillis();
		String sql = "alter table " + tableName + " add column `" + colName + "` " + colType + " ";
		Connection conn = null;
		PreparedStatement pstm = null;
		int i = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			i = pstm.executeUpdate();

			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.addCol>>執行SQL: {}, 耗時: {}ms", sql, t2 - t1);
			log.info("MysqlUtil.addCol>>傳入的參數值tableName:{},colName:{},colType:{}", tableName, colName, colType);
			log.info("MysqlUtil.addCol => added column succeeded!");
		} catch (Exception e) {
			log.error("MysqlUtil.addCol>>執行SQL: {}", sql);
			log.error("MysqlUtil.addCol>>傳入的參數值tableName:{},colName:{},colType:{}", tableName, colName, colType);
			log.error("MysqlUtil.addCol log error! errorMsg:", e);
		} finally {
			close(null, pstm, conn);
		}
		return i;
	}

	/**
	 * 爲某一個表批量添加列
	 *
	 * @param colInfo   要新增的列信息 key爲列名,value爲列類型
	 * @param tableName 表名
	 * @return 受影響的行數
	 */
	public static int addCol(Map<String, String> colInfo, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (colInfo == null || colInfo.size() == 0) {
			log.error("MysqlUtil.addCol Parameter[colInfo] is empty !  Directly return!");
			log.error("Please Attention :Empty parameter calls are illegal !");
			return 0;
		}
		long t1 = System.currentTimeMillis();
		StringBuilder sql = new StringBuilder("ALTER TABLE " + tableName + " ADD ( ");
		int i = 1;
		for (String colName : colInfo.keySet()) {
			if (i != colInfo.size()) {
				sql.append(" `" + colName + "` " + colInfo.get(colName) + " , ");
				i++;
			} else {
				sql.append(" `" + colName + "` " + colInfo.get(colName));
			}
		}
		sql.append(" )");

		Connection conn = null;
		PreparedStatement pstm = null;
		int re = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql.toString());
			re = pstm.executeUpdate();

			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.addCol>>執行SQL: {}, 耗時: {}ms", sql, t2 - t1);
			log.info("MysqlUtil.addCol>>傳入的參數值tableName:{},colInfo:{}", tableName, colInfo.toString());
			log.info("MysqlUtil.addCol => added column succeeded!");
		} catch (Exception e) {
			log.error("MysqlUtil.addCol>>執行SQL: {}", sql);
			log.error("MysqlUtil.addCol>>傳入的參數值tableName:{},colInfo:{}", tableName, colInfo.toString());
			log.error("MysqlUtil.addCol log error! errorMsg:", e);
		} finally {
			close(null, pstm, conn);
		}
		return re;
	}

	/**
	 * 變更列長度,注意僅適用於varchar類型字段
	 *
	 * @param colName
	 * @param colLen
	 * @param tableName
	 * @return 返回受影響的行數
	 */
	public static int addColLength(String colName, int colLen, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		long t1 = System.currentTimeMillis();
		String sql = "alter table " + tableName + " modify column `" + colName + "` varchar(" + colLen + ") default null ";
		Connection conn = null;
		PreparedStatement pstm = null;
		int i = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			i = pstm.executeUpdate();

			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.addColLength>>執行SQL: {}, 耗時: {}ms", sql, t2 - t1);
			log.info("MysqlUtil.addColLength>>傳入的參數值tableName:{},colName:{}", tableName, colName);
			log.info("MysqlUtil.addColLength => extend column length succeeded!");
		} catch (Exception e) {
			log.error("MysqlUtil.addColLength>>執行SQL: {}", sql);
			log.error("MysqlUtil.addColLength>>傳入的參數值tableName:{},colLen:{},colName:{}", tableName, colLen, colName);
			log.error("MysqlUtil.addColLength log error! errorMsg:", e);
		} finally {
			close(null, pstm, conn);
		}
		return i;
	}

	/**
	 * 變更列名列屬性
	 *
	 * @param oldColName 舊列名
	 * @param newColName 新列名
	 * @param newColType 新的列類型
	 * @param addition   附加的約束語句 如default null COMMENT '主鍵' 等
	 * @param tableName  表名
	 * @return 受影響的行數
	 */
	public static int changeColInfo(String oldColName, String newColName, String newColType, String addition, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		long t1 = System.currentTimeMillis();
		String sql = "alter table " + tableName + " change  `" + oldColName + "` `" + newColName + "` " + newColType + " ";
		if (addition != null && addition.length() != 0) {
			sql += addition;
		}
		Connection conn = null;
		PreparedStatement pstm = null;
		int i = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);
			i = pstm.executeUpdate();

			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.changeColInfo>>執行SQL: {}, 耗時: {}ms", sql, t2 - t1);
			log.info("MysqlUtil.changeColInfo>>傳入的參數值tableName:{},oldColName:{},newColName:{},newColType:{}", tableName, oldColName, newColName, newColType);
			log.info("MysqlUtil.changeColInfo => extend column length succeeded!");
		} catch (Exception e) {
			log.error("MysqlUtil.changeColInfo>>執行SQL: {}", sql);
			log.error("MysqlUtil.changeColInfo>>傳入的參數值tableName:{},oldColName:{},newColName:{},newColType:{}", tableName, oldColName, newColName, newColType);
			log.error("MysqlUtil.changeColInfo log error! errorMsg:", e);
		} finally {
			close(null, pstm, conn);
		}
		return i;
	}

	// alter table 表 change 修改前字段名 修改後字段名稱 int(12) not null,
	// change 修改前字段名 修改後字段名稱 varchar(11) not null COMMENT '主鍵',
	// change 修改前字段名 修改後字段名稱 varchar(11) not null,
	// change 修改前字段名 修改後字段名稱 varchar(11) not null,
	// change 修改前字段名 修改後字段名稱 varchar(11) not null

	/**
	 * 批量修改列名列屬性
	 *
	 * @param colInfo   要更改的列信息  注意key爲oldColName[不加`],value 爲  newColName varchar(11) not null COMMENT '主鍵' 格式[newColName最好前後加的有`]
	 * @param tableName 表名
	 * @return 受影響的行數
	 * @appraise 贊
	 * @remark 注意newColInfo的寫法爲  列類型和列約束
	 */
	public static int changeColInfo(Map<String, String> colInfo, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (colInfo == null || colInfo.size() == 0) {
			log.error("MysqlUtil.insert Parameter[colInfoList] is empty !  Directly return!");
			return 0;
		}
		long t1 = System.currentTimeMillis();

		StringBuilder sql = new StringBuilder("alter table " + tableName + " ");
		int i = 0;
		for (String oldColName : colInfo.keySet()) {
			String newColInfo = colInfo.get(oldColName);

			if (i != colInfo.size() - 1) {
				sql.append(" change  `" + oldColName + "` " + newColInfo + " ,");
				i++;
			} else {
				sql.append(" change  `" + oldColName + "` " + newColInfo + " ");
			}

		}

		Connection conn = null;
		PreparedStatement pstm = null;
		int re = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql.toString());
			re = pstm.executeUpdate();

			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.changeColInfo>>執行SQL: {}, 耗時: {}ms", sql, t2 - t1);
			log.info("MysqlUtil.changeColInfo>>傳入的參數值tableName:{},colInfo:{}", tableName, colInfo.toString());
			log.info("MysqlUtil.changeColInfo => extend column length succeeded!");
		} catch (Exception e) {
			log.error("MysqlUtil.changeColInfo>>執行SQL: {}", sql);
			log.error("MysqlUtil.changeColInfo>>傳入的參數值tableName:{},colInfo:{}", tableName, colInfo.toString());
			log.error("MysqlUtil.changeColInfo log error! errorMsg:", e);
		} finally {
			close(null, pstm, conn);
		}
		return re;
	}

	/**
	 * 依據列名列值id和表名更新列數據
	 *
	 * @param colName   列名
	 * @param colValue  列值
	 * @param id        注意列名就是id[重要!]
	 * @param tableName
	 * @return true or false
	 */
	public static boolean insertData(String colName, String colValue, Object id, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		long t1 = System.currentTimeMillis();
		String sql = " update " + tableName + " set `" + colName + "` = ?  where id = ?";
		Connection conn = null;
		PreparedStatement pstm = null;
		int i = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql);

			pstm.setString(1, colValue);
			pstm.setObject(2, id);
			i = pstm.executeUpdate();

			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.insertData>>執行SQL: {}, 耗時: {}ms", sql, t2 - t1);
			log.info("MysqlUtil.insertData>>傳入的參數值colName:{},colValue:{},id:{},tableName:{}", colName, colValue, id, tableName);
			log.info("MysqlUtil.insertData => insert data succeeded!");
		} catch (Exception e) {
			log.error("MysqlUtil.insertData>>執行SQL: {}", sql);
			log.error("MysqlUtil.insertData>>傳入的參數值colName:{},colValue:{},id:{},tableName:{}", colName, colValue, id, tableName);
			log.error("MysqlUtil.insertData log error! errorMsg:", e);
		} finally {
			close(null, pstm, conn);
		}
		return i == 0 ? false : true;
	}

	/**
	 * JsonObject型數據,整數據插入
	 *
	 * @param dataMap    Gson 家的JsonObject
	 * @param tableName  目標表名
	 * @param isIgnoreId 是否忽略id,如果你要插入的表的id列有自己的主鍵生成方案,請設置爲true,不插入jsonObject中的id屬性,
	 *                   反之設置爲false,將jsonObject中的id屬性值插入表中,如jsonObject中不包含id屬性,則設置爲true或false均可
	 * @return true or false 插入成功與否
	 * @Attention 注意dataMap的key名就是列名
	 * @remark 如果插入的數據爲字符串類型, 而目標列是數字類型如int, bigint, mysql會自動將其轉化爲數字類型插入
	 */
	public static boolean insert(JsonObject dataMap, String tableName, boolean isIgnoreId) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (dataMap == null || dataMap.size() == 0) {
			log.error("MysqlUtil.insert Parameter[dataMap] is empty !  Directly return!");
			return false;
		}

		long t0 = System.currentTimeMillis();

		// 如果忽略id則刪之
		if (isIgnoreId == true && dataMap.has("id")) {
			dataMap.remove("id");
		}
		StringBuilder sql = new StringBuilder();
		StringBuilder p = new StringBuilder();
		sql.append("insert into  " + tableName + "( ");
		for (String colName : dataMap.keySet()) {
			sql.append("`" + colName + "`,");
			p.append("'" + GsonUtil.getString(colName, dataMap) + "',");
		}
		sql.deleteCharAt(sql.length() - 1).append(") values(").append(p.deleteCharAt(p.length() - 1)).append(")");

		Connection conn = null;
		PreparedStatement pstm = null;

		int re = 0;
		try {
			conn = dataSource.getConnection();
			pstm = conn.prepareStatement(sql.toString());
			re = pstm.executeUpdate();

			long t1 = System.currentTimeMillis();
			log.info("MysqlUtil.insert>>執行SQL: {}, 耗時: {}ms", sql, t1 - t0);
			log.info("MysqlUtil.insert>>傳入的參數=>tableName:{}", tableName);
			log.info("MysqlUtil.insert => add new data succeeded!");
		} catch (Exception e) {
			try {
				if (e instanceof MySQLIntegrityConstraintViolationException) {
					// 完整性約束,多常見於主鍵衝突, Duplicate key 情況
					log.error("MysqlUtil.insert>>Exception :", e);
				} else {
					log.error("MysqlUtil.insert>>執行SQL: {}", sql);
					log.error("MysqlUtil.insert>>傳入的參數=>tableName:{}", tableName);
					log.error("MysqlUtil.insert log error! errorMsg:", e);
				}
			} catch (Exception e1) {
				log.error("Exception :", e1);
			}
		} finally {
			close(null, pstm, conn);
		}
		return re == 0 ? false : true;
	}

	/**
	 * 插入List<JsonObject> 內含批處理
	 *
	 * @param data
	 * @param tableName
	 * @param isIgnoreId 是否忽略id,如果你要插入的表的id列有自己的主鍵生成方案,請設置爲true,不插入jsonObject中的id屬性,
	 *                   反之設置爲false,將jsonObject中的id屬性值插入表中,如jsonObject中不包含id屬性,則設置爲true或false均可
	 * @return int[]  受影響的行數組成的數組,順序與執行的SQL相同
	 * @Attention 注意List<JsonObject>中的JsonObject的key名就是列名
	 */

	public static int[] insert(List<JsonObject> data, String tableName, boolean isIgnoreId) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (data == null || data.size() == 0) {
			log.error("MysqlUtil.insert Parameter[data] is empty !  Directly return!");
			return null;
		}

		long t0 = System.currentTimeMillis();

		Connection conn = null;
		Statement stm = null;
		// PreparedStatement pstm = null;
		try {
			conn = dataSource.getConnection();
			conn.setAutoCommit(false);
			stm = conn.createStatement();

			for (JsonObject dataMap : data) {
				// 如果配置爲忽略id,則刪之 _
				if (isIgnoreId == true) {
					dataMap.remove("id");
				}
				StringBuilder sql = new StringBuilder("insert into  " + tableName + "( ");
				StringBuilder p = new StringBuilder();
				sql.append("insert into  " + tableName + "( ");
				for (String colName : dataMap.keySet()) {
					sql.append("`" + colName + "`,");
					p.append("'" + GsonUtil.getString(colName, dataMap) + "',");
				}
				sql.deleteCharAt(sql.length() - 1).append(") values(").append(p.deleteCharAt(p.length() - 1)).append(")");
				log.info("MysqlUtil.insert>>執行SQL:{}", sql.toString());
				stm.addBatch(sql.toString());
			}

			int[] executeBatch = stm.executeBatch();
			conn.commit();// 執行完後,手動提交事務,不然回滾,傷...
			conn.setAutoCommit(true);

			long t1 = System.currentTimeMillis();
			log.info("MysqlUtil.insert>>執行SQL耗時:{}ms", t1 - t0);
			log.info("MysqlUtil.insert>>傳入的參數=>List.size:{},tableName:{},isIgnoreId:{}", data.size(), tableName, isIgnoreId);
			log.info("MysqlUtil.insert => add new data succeeded!");
			log.info("MysqlUtil.insert>>執行結果 batchresult=>size:{},data:{}", executeBatch.length, Arrays.toString(executeBatch));
			return executeBatch;
		} catch (Exception e) {
			try {
				conn.rollback();
				if (e instanceof MySQLIntegrityConstraintViolationException) {
					// 完整性約束之主鍵衝突 Duplicate key 情況
					log.error("MysqlUtil.insert>>Exception :", e);
				} else {
					log.error("MysqlUtil.insert>>執行SQL: {}", "SQL List太長,不打印之..");
					log.error("MysqlUtil.insert>>傳入的參數=>tableName:{}", tableName);
					log.error("MysqlUtil.insert log error! errorMsg:", e);
				}
			} catch (Exception e1) {
				log.error("Exception :", e1);
			}
		} finally {
			close(null, stm, conn);
		}
		return null;
	}

	/**
	 * 依據id集合刪除數據 ,注意依賴的字段爲id[注意字段名就是id]
	 *
	 * @param idList    id集合
	 * @param tableName
	 * @return int[]  受影響的行數組成的數組,順序與執行的SQL相同
	 */
	public static int[] delete(List<Object> idList, String tableName) {
		log.info("{}.{} Welcome to your arrival!", Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		if (idList == null || idList.size() == 0) {
			log.error("MysqlUtil.delete Parameter[idList] is empty !  Return !");
			return null;
		}
		long t1 = System.currentTimeMillis();

		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;

		String sql = "delete from " + tableName + " where id = ?";

		try {
			conn = dataSource.getConnection();
			conn.setAutoCommit(false);

			pstm = conn.prepareStatement(sql);
			for (Object id : idList) {
				pstm.setObject(1, id);
				pstm.addBatch();
			}
			int[] executeBatch = pstm.executeBatch();
			conn.commit();// 執行完後,手動提交事務,不然回滾,傷...
			conn.setAutoCommit(true);// 再把自動提交打開,正常就是要自動提交的
			long t2 = System.currentTimeMillis();
			log.info("MysqlUtil.delete>>執行SQL: {}, 耗時: {}ms", sql.toUpperCase(), t2 - t1);
			log.info("MysqlUtil.delete>>傳入的參數值idList=>size:{},data:{}", idList.size(), Arrays.toString(idList.toArray()));
			log.info("MysqlUtil.delete>>執行成功,返回結果 batchresult=>size:{},data:{}", executeBatch.length, Arrays.toString(executeBatch));
			return executeBatch;
		} catch (Exception e) {
			try {
				conn.rollback();
				log.error("MysqlUtil.delete>>執行SQL: {}", sql);
				log.error("MysqlUtil.delete>>傳入的參數值idList=>{}", Arrays.toString(idList.toArray()));
				log.error("MysqlUtil.delete log error!", e);
			} catch (SQLException e1) {
				log.error("Exception :", e1);
			}
		} finally {
			close(rs, pstm, conn);
		}
		return null;
	}

	/**
	 * 將目標sql中的?全部替換成params裏的參數
	 *
	 * @param params 參數列表
	 * @param sql    SQL語句
	 * @return 替換完佔位符的SQL語句
	 */
	public static String setParam(List<Object> params, String sql) {
		String[] split = sql.split("\\?");
		if (params.size() != split.length - 1) {
			log.error("MysqlUtil.setParam>>The number of parameters is not valid !");
			log.error("MysqlUtil.setParam>>傳入的SQL:{}", sql);
			log.error("MysqlUtil.setParam>>傳入的參數值params:{}", params);
			return sql;
		}
		StringBuilder stb = new StringBuilder();
		for (int i = 0; i < params.size(); i++) {
			stb.append(split[i]).append(getObjectStr(params.get(i)));
		}
		return stb.append(split[params.size()]).toString();
	}

	/**
	 * 將目標sql中的?全部替換成params裏對應的value參數
	 *
	 * @param params 參數列表,包含key參數位置,value參數值
	 * @param sql    目標SQL語句
	 * @return 替換完佔位符的SQL語句
	 */
	public static String setParam(Map<Integer, Object> params, String sql) {
		sql+="  ";//?處於最後一個會導致切出來的字符串數量少一個
		String[] split = sql.split("\\?");
		if (params.size() != split.length - 1) {
			log.error("MysqlUtil.setParam>>The number of parameters is not valid !");
			log.error("MysqlUtil.setParam>>傳入的SQL:{}", sql);
			log.error("MysqlUtil.setParam>>要替換的參數數量:{},傳入的參數數量:{},參數值params:{}", (split.length - 1), params.size(), params.toString());
			return sql;
		}
		StringBuilder stb = new StringBuilder();
		for (int i = 0; i < params.size(); i++) {
			stb.append(split[i]).append(getObjectStr(params.get(i + 1)));
		}
		return stb.append(split[params.size()]).toString();
	}

	/**
	 * 判斷字符是否爲空或空白字符串
	 */
	private static boolean isBlank(String str) {
		return str == null || str.length() == 0 || str.trim().equals("");
	}

	/**
	 * 判斷字符是否不爲空或空白字符串組成
	 */
	private static boolean isNotBlank(String str) {
		return !isBlank(str);
	}

	/**
	 * 判斷字符是否爲空或空白字符串,或各種null組成
	 */
	private static boolean isNull(String str) {
		return str == null || str.length() == 0 || "".equals(str.trim()) || "NULL".equals(str.trim().toUpperCase());
	}

	/**
	 * 判斷字符是否不爲空或空白字符串,或各種null組成
	 */
	private static boolean isNotNull(String str) {
		return str == null || str.length() == 0 || "".equals(str.trim()) || "NULL".equals(str.trim().toUpperCase());
	}

	/**
	 * 將傳入的Object參數替換成目標字符串
	 *
	 * @param x
	 * @return mysql需要的字符串
	 * @version 1.2.0
	 * @Attention 暫不支持枚舉
	 */
	@SuppressWarnings("deprecation")
	private static String getObjectStr(Object x) {

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

		Class<?> clazz = x.getClass();
		if (clazz == Integer.class) {
			return (Integer) x + "";
		} else

		if (clazz == Long.class) {
			return (Long) x + "";
		} else

		if (clazz == String.class) {
			return "'" + (String) x + "'";
		} else

		// Boolean 型對象mysql的tinyint類型 1爲true.0爲false
		if (clazz == Boolean.class) {
			if ((Boolean) x) {
				return 1 + "";
			} else {
				return 0 + "";
			}
		} else

		if (clazz == Byte.class) {// 對應tinyint
			return (Byte) x + "";
		} else

		if (clazz == Short.class) {// 對應smallint
			return (Short) x + "";
		} else

		if (clazz == Float.class) {
			return (Float) x + "";
		} else

		if (clazz == Double.class) {
			return (Double) x + "";
		} else

		if (clazz == BigDecimal.class) {
			return (BigDecimal) x + "";
		} else

		if (clazz == java.sql.Date.class) {
			return ((java.sql.Date) x).toLocaleString();
		} else

		if (clazz == java.util.Date.class) {
			return ((java.util.Date) x).toLocaleString();
		} else

		if (clazz == java.sql.Timestamp.class) {
			return ((java.sql.Timestamp) x).toLocaleString();
		} else

		if (clazz == java.sql.Time.class) {
			return ((java.sql.Time) x).toLocaleString();
		} else

		if (clazz == byte[].class) {
			StringBuilder stb = new StringBuilder();
			for (byte b : (byte[]) x) {
				stb.append(b);
			}
			return stb.toString();
		} else

		if (clazz == short[].class) {
			StringBuilder stb = new StringBuilder();
			for (short b : (short[]) x) {
				stb.append(b + ",");
			}
			return stb.deleteCharAt(stb.length() - 1).toString();
		} else

		if (clazz == int[].class) {
			StringBuilder stb = new StringBuilder();
			for (int i : (int[]) x) {
				stb.append(i + ",");
			}
			return stb.deleteCharAt(stb.length() - 1).toString();
		} else

		if (clazz == long[].class) {
			StringBuilder stb = new StringBuilder();
			for (long l : (long[]) x) {
				stb.append(l + ",");
			}
			return stb.deleteCharAt(stb.length() - 1).toString();
		} else

		if (clazz == char[].class) {
			StringBuilder stb = new StringBuilder();
			for (char c : (char[]) x) {
				stb.append(c);
			}
			return stb.toString();
		} else

		if (clazz == String[].class) {
			StringBuilder stb = new StringBuilder();
			for (char c : (char[]) x) {
				stb.append(c + ",");
			}
			return stb.deleteCharAt(stb.length() - 1).toString();
		} else

		if (x instanceof List) {
			StringBuilder stb = new StringBuilder();
			for (Object obj : (List<?>) x) {
				stb.append(obj.toString() + ",");
			}
			return stb.deleteCharAt(stb.length() - 1).toString();
		} else
		// 可以考慮下下面幾種情況怎麼處理
		// 一律返回null好了
		if (x instanceof InputStream) {
		} else

		if (x instanceof Reader) {
		} else

		if (x instanceof Clob) {
		} else

		if (x instanceof NClob) {
		} else

		if (x instanceof Blob) {
		}

		return null;
	}

	static {
		// 生產數據庫 MySQL
		String driver = PropertiesUtil.getString("jdbc.mysql.driver");
		String url = PropertiesUtil.getString("jdbc.mysql.url");
		String username = PropertiesUtil.getString("jdbc.mysql.username");
		String password = PropertiesUtil.getString("jdbc.mysql.password");

		// 47.94.191.230 測試服 MySQL數據庫
		// String driver = PropertiesUtil.getString("windowsmysqldrivername");
		// String url = PropertiesUtil.getString("windowsmysqlurl");
		// String username = PropertiesUtil.getString("windowsmysqlusername");
		// String password = PropertiesUtil.getString("windowsmysqlpassword");

		// 本機 數據庫,當部署到230機子上時也可以自動連接230機上的MySQL
		// String driver = PropertiesUtil.getString("localhostmysqldrivername");
		// String url = PropertiesUtil.getString("localhostmysqlurl");
		// String username = PropertiesUtil.getString("localhostmysqlusername");
		// String password = PropertiesUtil.getString("localhostmysqlpassword");

		// 配置DataSource
		dataSource.setDriverClassName(driver);
		dataSource.setUrl(url);
		dataSource.setUsername(username);
		dataSource.setPassword(password);

		// 需要配置的四個參數項
		dataSource.setName("kg_datasource_jfai-DruidDataSource-wanglf-" + (100000 + (new Random()).nextInt(900000)));
		dataSource.setInitialSize(20);// 初始化連接數量
		dataSource.setMaxActive(1600);// 最大併發連接數
		dataSource.setMinIdle(16);// 最小空閒連接數

		dataSource.setMaxWait(60000);// 獲取連接等待超時的時間,單位是毫秒
		dataSource.setRemoveAbandoned(true);// 超過時間限制是否回收
		dataSource.setRemoveAbandonedTimeout(180);// 超過時間限制多長 單位s
		dataSource.setTimeBetweenEvictionRunsMillis(600000);// 間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒
		dataSource.setLogAbandoned(true); // 一旦發生Abandoned事件是否輸出log
		dataSource.setMinEvictableIdleTimeMillis(300000);// 配置一個連接在池中最小生存的時間,單位是毫秒
		dataSource.setValidationQuery("SELECT 1");// 用來檢測連接是否有效的sql,要求是一個查詢語句
		dataSource.setTestWhileIdle(true);// 申請連接的時候檢測是否有空閒連接
		// druidDataSource.setTestOnBorrow(true);
		// 申請連接時執行validationQuery檢測連接是否有效,配置爲true會降低性能
		// druidDataSource.setTestOnReturn(true);
		// 歸還連接時執行validationQuery檢測連接是否有效,配置爲true會降低性能
		dataSource.setPoolPreparedStatements(true);// 打開PSCache
		dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);// 指定每個連接上PSCache的大小
		dataSource.setMaxOpenPreparedStatements(120);
		dataSource.setMaxPoolPreparedStatementPerConnectionSize(100);
		dataSource.setAccessToUnderlyingConnectionAllowed(true);
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章