有時(shí)候需要連接第三方的各種數(shù)據(jù)源,總是要去寫不同的代碼,于是將MaxCompute, Hive, Oracle, Mysql等JDBC連接封裝起來,只需要傳入不同的參數(shù)即可創(chuàng)建一個(gè)不同類型的連接池。
連接參數(shù)基礎(chǔ)類封裝
封裝了JDBC基礎(chǔ)的連接參數(shù),如果不需要這些屬性可以繼承該類,增加新的屬性即可。
@Data
public class BaseJdbcConnParam implements Serializable {
? ? /**
? ? * driver name
? ? */
? ? private String driverName;
? ? /**
? ? * IP
? ? */
? ? private String ip;
? ? /**
? ? * db server port
? ? */
? ? private Integer port;
? ? /**
? ? * db name
? ? */
? ? private String dbName;
? ? /**
? ? * db connection username
? ? */
? ? private String username;
? ? /**
? ? * db connection password
? ? */
? ? private String password;
}
抽象連接工具類封裝
功能如下:
1、構(gòu)造函數(shù):根據(jù)連接參數(shù)不同構(gòu)建不同的連接對象
2、構(gòu)建具體的連接,子類實(shí)現(xiàn)buildConnection()
3、獲取連接,構(gòu)建好之后直接獲取getConnection()
/**
* @Description 抽象連接工具類父類
* @Author itdl
* @Date 2022/08/15 09:54
*/
public abstract class AbstractConnUtil<P extends BaseJdbcConnParam> {
? ? /**
? ? * connection params
? ? */
? ? protected final P connParam;
? ? /**
? ? * jdbc connection object
? ? */
? ? protected final Connection connection;
? ? /**
? ? * 構(gòu)造函數(shù), 構(gòu)造工具類對象
? ? * @param connParam 連接參數(shù)
? ? */
? ? public AbstractConnUtil(P connParam) {
? ? ? ? this.connParam = connParam;
? ? ? ? this.connection = buildConnection();
? ? }
? ? /**
? ? * 構(gòu)建連接對象
? ? * @return 連接對象
? ? */
? ? protected abstract Connection buildConnection();
? ? /**
? ? * 獲取連接
? ? */
? ? public Connection getConnection() {
? ? ? ? return connection;
? ? }
}
連接池管理
功能如下:
1、根據(jù)不同的連接參數(shù),和最大連接數(shù)去創(chuàng)建一個(gè)對應(yīng)類型的連接池。
2、獲取連接方法,如果連接沒有了,等待其他線程釋放(最多等待十分鐘)
3、釋放連接方法,將連接放回連接池,然后喚醒等待的線程
4、關(guān)閉連接池所有的連接
/**
* @Description 連接池管理
* @Author itdl
* @Date 2022/08/16 09:42
*/
@Slf4j
public class DbConnPool<T extends BaseJdbcConnParam> {
? ? /**
? ? * 用于存放連接
? ? */
? ? private final LinkedList<Connection> connPool = new LinkedList<Connection>();
? ? /**
? ? * 最大連接池?cái)?shù)量
? ? */
? ? private final Integer maxPoolSize;
? ? private final T connParam;
? ? /**
? ? * 構(gòu)造函數(shù)
? ? * @param connParam 連接參數(shù)
? ? * @param maxPoolSize 連接池大小
? ? */
? ? public DbConnPool(T connParam, Integer maxPoolSize)? {
? ? ? ? this.maxPoolSize = maxPoolSize;
? ? ? ? this.connParam = connParam;
? ? ? ? // 初始化連接池
? ? ? ? for (int i = 0; i < maxPoolSize; i++) {
? ? ? ? ? ? connPool.addLast(this.createConnection());
? ? ? ? }
? ? }
? ? /**
? ? * 創(chuàng)建數(shù)據(jù)庫連接
? ? * @return 連接
? ? */
? ? private Connection createConnection() {
? ? ? ? if (connParam instanceof OracleJdbcConnParam){
? ? ? ? ? ? final OracleConnUtil util = new OracleConnUtil((OracleJdbcConnParam) connParam);
? ? ? ? ? ? return util.getConnection();
? ? ? ? }
? ? ? ? if (connParam instanceof HiveJdbcConnParam){
? ? ? ? ? ? final HiveConnUtil util = new HiveConnUtil((HiveJdbcConnParam) connParam);
? ? ? ? ? ? return util.getConnection();
? ? ? ? }
? ? ? ? if (connParam instanceof MysqlJdbcConnParam){
? ? ? ? ? ? final MysqlConnUtil util = new MysqlConnUtil((MysqlJdbcConnParam) connParam);
? ? ? ? ? ? return util.getConnection();
? ? ? ? }
? ? ? ? if (connParam instanceof MaxComputeJdbcConnParam){
? ? ? ? ? ? final MaxComputeJdbcUtil util = new MaxComputeJdbcUtil((MaxComputeJdbcConnParam) connParam);
? ? ? ? ? ? return util.getConnection();
? ? ? ? }
? ? ? ? throw new BizException(ResultCode.CONN_TYPE_NOT_SUPPORT);
? ? }
? ? /**
? ? * 獲取連接
? ? * @return 連接
? ? */
? ? public synchronized Connection getConnection(){
? ? ? ? if (connPool.size() == 0){
//? ? ? ? ? ? throw new BizException(ResultCode.CONN_POOL_EMPTY_ERR);
? ? ? ? ? ? // 最長等待十分鐘
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? log.info("==========連接池已經(jīng)空了, 請等待其他線程釋放==========");
? ? ? ? ? ? ? ? wait(10 * 60 * 1000);
? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? log.info("==========連接池已經(jīng)空了, 等待了10分鐘還沒有釋放,拋出異常==========");
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? throw new BizException(ResultCode.CONN_POOL_EMPTY_ERR);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? // 去除最上面一個(gè)連接 如果沒有連接了,將會拋出異常
? ? ? ? return connPool.removeFirst();
? ? }
? ? /**
? ? * 用完后釋放連接
? ? * @param conn 要釋放的連接
? ? */
? ? public synchronized void freeConnection(Connection conn){
? ? ? ? // 通知連接已經(jīng)釋放
? ? ? ? notifyAll();
? ? ? ? this.connPool.addLast(conn);
? ? }
? ? /**
? ? * 關(guān)閉連接池
? ? */
? ? public synchronized void close(){
? ? ? ? for (Connection connection : connPool) {
? ? ? ? ? ? SqlUtil.close(connection);
? ? ? ? }
? ? }
}
SQL操作工具類
根據(jù)連接對象Connection和數(shù)據(jù)庫房源,封裝不同的sql執(zhí)行。執(zhí)行SQL核心功能封裝。
/**
* @Description SQL操作工具類
* @Author itdl
* @Date 2022/08/10 17:13
*/
@Slf4j
public class SqlUtil {
? ? /**查詢mysql表注釋sql*/
? ? public static final String SELECT_TABLES_MYSQL = "select table_name, table_comment from information_schema.tables where TABLE_SCHEMA = '%s'";
? ? /**查詢MaxCompute表注釋sql*/
? ? public static final String SELECT_TABLES_MAX_COMPUTE = "select table_name, table_comment from information_schema.tables where TABLE_SCHEMA = '%s'";
? ? /**查詢oracle表注釋sql*/
? ? public static final String SELECT_TABLES_ORACLE = "SELECT t2.TABLE_NAME as table_name, t2.COMMENTS as table_comment FROM user_tables t1 inner join user_tab_comments t2 on t1.TABLE_NAME = t2.TABLE_NAME";
? ? /**查詢hive表注釋sql, 先查詢表名,根據(jù)表名獲取建表語句,正則提取表注釋*/
? ? public static final String SELECT_TABLES_HIVE = "show tables";
? ? public static final String SELECT_TABLES_2_HIVE = "describe extended %s";
? ? /**分頁數(shù)量統(tǒng)計(jì)Mysql*/
? ? private static final String SELECT_COUNT_MYSQL = "select count(1) from (%s) z";
? ? /**分頁數(shù)量統(tǒng)計(jì)MaxCompute*/
? ? private static final String SELECT_COUNT_MAX_COMPUTE = "select count(1) from (%s) z;";
? ? /**分頁數(shù)量統(tǒng)計(jì)Hive*/
? ? private static final String SELECT_COUNT_ORACLE = "select count(1) from (%s) z";
? ? /**分頁數(shù)量統(tǒng)計(jì)Oracle*/
? ? private static final String SELECT_COUNT_HIVE = "select count(1) from (%s) z";
? ? /**maxCompute開啟全表掃描sql*/
? ? private static final String FULL_SCAN_MAX_COMPUTE = "set odps.sql.allow.fullscan=true;";
? ? /**分頁查詢sql-Mysql*/
? ? private static final String SELECT_PAGE_MYSQL = "select z.* from (%s) z limit %s, %s";
? ? /**分頁查詢sql-MaxCompute*/
? ? private static final String SELECT_PAGE_MAX_COMPUTE = "select z.* from (%s) z limit %s, %s;";
? ? /**分頁查詢sql-Hive*/
? ? private static final String SELECT_PAGE_HIVE = "select * from (select row_number() over () as row_num_01,u.* from (%s) u) mm where mm.row_num_01 between %s and %s";
? ? /**分頁查詢sql-Oracle*/
? ? private static final String SELECT_PAGE_ORACLE = "select * from (SELECT ROWNUM as row_num_01,z.* from (%s) z) h where h.row_num_01 > %s and h.row_num_01 <= %s";
? ? /**數(shù)據(jù)庫連接*/
? ? private final Connection connection;
? ? /**數(shù)據(jù)庫方言*/
? ? private final Integer dbDialect;
? ? /**支持的方言列表*/
? ? private static final List<Integer> supportDbTypes =
? ? ? ? ? ? Arrays.asList(DbDialectEnum.ORACLE.getCode(), DbDialectEnum.HIVE.getCode(), DbDialectEnum.MYSQL.getCode(), DbDialectEnum.MAX_COMPUTE.getCode());
? ? public SqlUtil(Connection connection, Integer dbDialect) {
? ? ? ? if (!supportDbTypes.contains(dbDialect)){
? ? ? ? ? ? throw new BizException(ResultCode.CONN_TYPE_NOT_SUPPORT);
? ? ? ? }
? ? ? ? this.connection = connection;
? ? ? ? this.dbDialect = dbDialect;
? ? }
? ? /**
? ? * 根據(jù)connection獲取所有的表和對應(yīng)的注釋
? ? */
? ? public List<TableMetaInfo> getTables(String schemaName){
? ? ? ? List<TableMetaInfo> result = new ArrayList<>();
? ? ? ? String sql = "";
? ? ? ? switch (this.dbDialect){
? ? ? ? ? ? case 1:
? ? ? ? ? ? ? ? sql = SELECT_TABLES_ORACLE;
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 2:
? ? ? ? ? ? ? ? sql = SELECT_TABLES_HIVE;
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 3:
? ? ? ? ? ? ? ? if (StringUtils.isBlank(schemaName)){
? ? ? ? ? ? ? ? ? ? throw new BizException(ResultCode.SELECT_TABLES_SCHEMA_NOT_NULL_ERR);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? sql = String.format(SELECT_TABLES_MYSQL, schemaName);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 4:
? ? ? ? ? ? ? ? if (StringUtils.isBlank(schemaName)){
? ? ? ? ? ? ? ? ? ? throw new BizException(ResultCode.SELECT_TABLES_SCHEMA_NOT_NULL_ERR);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? sql = String.format(SELECT_TABLES_MAX_COMPUTE, schemaName);
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? if (StringUtils.isBlank(sql)){
? ? ? ? ? ? throw new BizException(ResultCode.CONN_TYPE_NOT_SUPPORT);
? ? ? ? }
? ? ? ? // 執(zhí)行SQL語句
? ? ? ? final List<LinkedHashMap<String, Object>> resultMaps = querySql(sql);
? ? ? ? if (ObjectUtils.isEmpty(resultMaps)){
? ? ? ? ? ? return Lists.newArrayList();
? ? ? ? }
? ? ? ? // hive單獨(dú)處理
? ? ? ? List<TableMetaInfo> result1 = getHiveTableMetaInfos(result, resultMaps);
? ? ? ? if (result1 != null) return result1;
? ? ? ? // 轉(zhuǎn)換結(jié)果
? ? ? ? return resultMaps.stream().map(
? ? ? ? ? ? ? ? m->{
? ? ? ? ? ? ? ? ? ? final TableMetaInfo info = new TableMetaInfo();
? ? ? ? ? ? ? ? ? ? Object tableNameObj = m.get("table_name");
? ? ? ? ? ? ? ? ? ? String tableName = tableNameObj == null ? m.get("TABLE_NAME") == null ? "" : String.valueOf(m.get("TABLE_NAME")) : String.valueOf(tableNameObj);
? ? ? ? ? ? ? ? ? ? Object tableCommentObj = m.get("table_comment");
? ? ? ? ? ? ? ? ? ? String tableComment = tableCommentObj == null ? m.get("TABLE_COMMENT") == null ? "" : String.valueOf(m.get("TABLE_COMMENT")) : String.valueOf(tableCommentObj);
? ? ? ? ? ? ? ? ? ? info.setTableName(tableName);
? ? ? ? ? ? ? ? ? ? info.setComment(tableComment);
? ? ? ? ? ? ? ? ? ? return info;
? ? ? ? ? ? ? ? }
? ? ? ? ).collect(Collectors.toList());
? ? }
? ? /**
? ? * 根據(jù)schemeName,表名獲取字段列表
? ? * @param tableName 一般是數(shù)據(jù)庫 oracle是用戶名
? ? */
? ? public List<TableColumnMetaInfo> getColumnsByTableName(String tableName){
? ? ? ? try {
? ? ? ? ? ? List<TableColumnMetaInfo> list = new ArrayList<>();
? ? ? ? ? ? final DatabaseMetaData metaData = connection.getMetaData();
? ? ? ? ? ? final ResultSet columns = metaData.getColumns(null, null, tableName, null);
? ? ? ? ? ? while (columns.next()){
? ? ? ? ? ? ? ? String columnName = columns.getString("COLUMN_NAME");
? ? ? ? ? ? ? ? String remarks = columns.getString("REMARKS");
? ? ? ? ? ? ? ? remarks = StringUtils.isBlank(remarks) ? "" : remarks;
? ? ? ? ? ? ? ? final TableColumnMetaInfo metaInfo = new TableColumnMetaInfo(tableName, columnName, remarks);
? ? ? ? ? ? ? ? list.add(metaInfo);
? ? ? ? ? ? }
? ? ? ? ? ? return list;
? ? ? ? } catch (SQLException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? return Lists.newArrayList();
? ? ? ? }
? ? }
? ? /**
? ? * 執(zhí)行sql查詢
? ? * @param querySql 查詢sql
? ? * @return List<Map<String, Object>> 通過LinkedHashMap接受,序列化時(shí)可保證順序一致
? ? */
? ? public List<LinkedHashMap<String, Object>> queryData(String querySql, boolean... fullScan){
? ? ? ? Statement statement = null;
? ? ? ? ResultSet resultSet = null;
? ? ? ? try {
? ? ? ? ? ? // 創(chuàng)建statement
? ? ? ? ? ? statement = this.connection.createStatement();
? ? ? ? ? ? // 執(zhí)行全表掃描sql
? ? ? ? ? ? for (boolean b : fullScan) {
? ? ? ? ? ? ? ? if (b){
? ? ? ? ? ? ? ? ? ? statement.execute(FULL_SCAN_MAX_COMPUTE);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? // 執(zhí)行查詢語句
? ? ? ? ? ? resultSet = statement.executeQuery(querySql);
? ? ? ? ? ? // 構(gòu)建結(jié)果返回
? ? ? ? ? ? return buildListMap(resultSet);
? ? ? ? } catch (SQLException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? throw new BizException(ResultCode.SQL_EXEC_ERR);
? ? ? ? } finally {
? ? ? ? ? ? // 關(guān)閉resultSet, statement
? ? ? ? ? ? close(resultSet, statement);
? ? ? ? }
? ? }
? ? /**
? ? * 執(zhí)行sql查詢
? ? * @param querySql 查詢sql
? ? * @return List<Map<String, Object>>
? ? */
? ? public List<LinkedHashMap<String, Object>> queryData(String querySql, Integer page, Integer size){
? ? ? ? Statement statement = null;
? ? ? ? ResultSet resultSet = null;
? ? ? ? try {
? ? ? ? ? ? // 1、替換分號
? ? ? ? ? ? querySql = querySql.replaceAll(";", "");
? ? ? ? ? ? // 創(chuàng)建statement
? ? ? ? ? ? statement = this.connection.createStatement();
? ? ? ? ? ? // 2、格式化SQL
? ? ? ? ? ? int offset = (page - 1 ) * size;
? ? ? ? ? ? String execSql = "";
? ? ? ? ? ? switch (this.dbDialect){
? ? ? ? ? ? ? ? case 1:
? ? ? ? ? ? ? ? ? ? // oracle
? ? ? ? ? ? ? ? ? ? execSql = String.format(SELECT_PAGE_ORACLE, querySql, offset, size);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case 2:
? ? ? ? ? ? ? ? ? ? // hive
? ? ? ? ? ? ? ? ? ? execSql = String.format(SELECT_PAGE_HIVE, querySql, offset, size);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case 3:
? ? ? ? ? ? ? ? ? ? // mysql
? ? ? ? ? ? ? ? ? ? execSql = String.format(SELECT_PAGE_MYSQL, querySql, offset, size);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case 4:
? ? ? ? ? ? ? ? ? ? // maxCompute
? ? ? ? ? ? ? ? ? ? execSql = String.format(SELECT_PAGE_MAX_COMPUTE, querySql, offset, size);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? // maxCompute開啟全表掃描
? ? ? ? ? ? if (DbDialectEnum.MAX_COMPUTE.getCode().equals(this.dbDialect)){
? ? ? ? ? ? ? ? statement.execute(FULL_SCAN_MAX_COMPUTE);
? ? ? ? ? ? }
? ? ? ? ? ? log.info("=======>>>執(zhí)行分頁sql為:{}", execSql);
? ? ? ? ? ? // 執(zhí)行查詢語句
? ? ? ? ? ? resultSet = statement.executeQuery(execSql);
? ? ? ? ? ? // 構(gòu)建結(jié)果返回
? ? ? ? ? ? return buildListMap(resultSet);
? ? ? ? } catch (SQLException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? throw new BizException(ResultCode.SQL_EXEC_ERR);
? ? ? ? } finally {
? ? ? ? ? ? // 關(guān)閉resultSet, statement
? ? ? ? ? ? close(resultSet, statement);
? ? ? ? }
? ? }
? ? /**
? ? * 執(zhí)行分頁查詢
? ? * @param querySql 分頁查詢sql
? ? * @param page 頁碼 從1開始 第n頁傳n
? ? * @param size 每頁記錄數(shù)
? ? * @return 分頁查詢結(jié)果
? ? */
? ? public PageResult<LinkedHashMap<String, Object>> pageQueryMap(String querySql, Integer page, Integer size){
? ? ? ? // 1、替換分號
? ? ? ? querySql = querySql.replaceAll(";", "");
? ? ? ? String countSql = "";
? ? ? ? switch (this.dbDialect){
? ? ? ? ? ? case 1:
? ? ? ? ? ? ? ? // oracle
? ? ? ? ? ? ? ? countSql = String.format(SELECT_COUNT_ORACLE, querySql);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 2:
? ? ? ? ? ? ? ? // hive
? ? ? ? ? ? ? ? countSql = String.format(SELECT_COUNT_HIVE, querySql);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 3:
? ? ? ? ? ? ? ? // mysql
? ? ? ? ? ? ? ? countSql = String.format(SELECT_COUNT_MYSQL, querySql);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 4:
? ? ? ? ? ? ? ? // maxCompute
? ? ? ? ? ? ? ? countSql = String.format(SELECT_COUNT_MAX_COMPUTE, querySql);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? log.info("=======>>>執(zhí)行分頁統(tǒng)計(jì)總數(shù)sql為:{}", countSql);
? ? ? ? // 查詢總數(shù)
? ? ? ? final List<LinkedHashMap<String, Object>> countMap = queryData(countSql, DbDialectEnum.MAX_COMPUTE.getCode().equals(this.dbDialect));
? ? ? ? if (CollectionUtils.isEmpty(countMap)){
? ? ? ? ? ? return new PageResult<>(0L, new ArrayList<>());
? ? ? ? }
? ? ? ? long count = 0L;
? ? ? ? for (Object value : countMap.get(0).values()) {
? ? ? ? ? ? count = Long.parseLong(String.valueOf(value));
? ? ? ? }
? ? ? ? if (count == 0){
? ? ? ? ? ? return new PageResult<>(0L, new ArrayList<>());
? ? ? ? }
? ? ? ? // 執(zhí)行分頁查詢 開啟全表掃描
? ? ? ? final List<LinkedHashMap<String, Object>> resultList = queryData(querySql, page, size);
? ? ? ? return new PageResult<>(count, resultList);
? ? }
? ? /**
? ? * 執(zhí)行分頁查詢
? ? * @param querySql 分頁查詢sql
? ? * @param page 頁碼 從1開始 第n頁傳n
? ? * @param size 每頁記錄數(shù)
? ? * @return 分頁查詢結(jié)果
? ? */
? ? public <T>PageResult<T> pageQuery(String querySql, Integer page, Integer size, Class<T> clazz){
? ? ? ? final PageResult<LinkedHashMap<String, Object>> result = pageQueryMap(querySql, page, size);
? ? ? ? List<T> rows = new ArrayList<>();
? ? ? ? for (LinkedHashMap<String, Object> row : result.getRows()) {
? ? ? ? ? ? final T t = JSONObject.parseObject(JSONObject.toJSONString(row), clazz);
? ? ? ? ? ? rows.add(t);
? ? ? ? }
? ? ? ? return new PageResult<>(result.getTotal(), rows);
? ? }
? ? /**
? ? * 獲取hive的表注釋
? ? * @param result 結(jié)果
? ? * @param resultMaps show tables結(jié)果
? ? * @return List<TableMetaInfo>
? ? */
? ? private List<TableMetaInfo> getHiveTableMetaInfos(List<TableMetaInfo> result, List<LinkedHashMap<String, Object>> resultMaps) {
? ? ? ? if (dbDialect.equals(DbDialectEnum.HIVE.getCode())){
? ? ? ? ? ? for (LinkedHashMap<String, Object> resultMap : resultMaps) {
? ? ? ? ? ? ? ? final String tabName = String.valueOf(resultMap.get("tab_name"));
? ? ? ? ? ? ? ? final String descTableCommentSql = String.format(SELECT_TABLES_2_HIVE, tabName);
? ? ? ? ? ? ? ? List<LinkedHashMap<String, Object>> resultMapsComments = querySql(descTableCommentSql);
//? ? ? ? ? ? ? ? col_name -> Detailed Table Information
? ? ? ? ? ? ? ? String comments = resultMapsComments.stream()
? ? ? ? ? ? ? ? ? ? ? ? .filter(m -> "Detailed Table Information".equals(m.get("col_name")))
? ? ? ? ? ? ? ? ? ? ? ? .map(m -> String.valueOf(m.get("data_type"))).findFirst()
? ? ? ? ? ? ? ? ? ? ? ? .orElse("");
? ? ? ? ? ? ? ? comments = ReUtil.get("parameters:\\{(?!.*?\\().*transient_lastDdlTime.*?comment=(.*?)\\}", comments,1);
? ? ? ? ? ? ? ? if (StringUtils.isBlank(comments)) {
? ? ? ? ? ? ? ? ? ? comments = "";
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (comments.contains(",")){
? ? ? ? ? ? ? ? ? ? comments = comments.substring(0, comments.lastIndexOf(","));
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? result.add(new TableMetaInfo(tabName, comments));
? ? ? ? ? ? ? ? log.info("===========>>>獲取表{}的注釋成功:{}", tabName, comments);
? ? ? ? ? ? ? ? resultMapsComments.clear();
? ? ? ? ? ? }
? ? ? ? ? ? return result;
? ? ? ? }
? ? ? ? return null;
? ? }
? ? /**
? ? * 執(zhí)行SQL查詢
? ? * @param sql sql語句
? ? * @return 數(shù)據(jù)列表,使用LinkedHashMap是為了防止HashMap序列化后導(dǎo)致順序亂序
? ? */
? ? public List<LinkedHashMap<String, Object>> querySql(String sql){
? ? ? ? // 執(zhí)行sql
? ? ? ? Statement statement = null;
? ? ? ? ResultSet resultSet = null;
? ? ? ? try {
? ? ? ? ? ? statement = connection.createStatement();
? ? ? ? ? ? resultSet = statement.executeQuery(sql);
? ? ? ? ? ? return buildListMap(resultSet);
? ? ? ? } catch (SQLException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? throw new BizException(ResultCode.SQL_EXEC_ERR);
? ? ? ? }finally {
? ? ? ? ? ? // 關(guān)閉
? ? ? ? ? ? close(resultSet, statement);
? ? ? ? }
? ? }
? ? /**
? ? * 關(guān)閉對象 傳入多個(gè)時(shí)注意順序, 需要先關(guān)閉哪個(gè)就傳在參數(shù)前面
? ? * @param objs 對象動態(tài)數(shù)組
? ? */
? ? public static void close(Object ...objs){
? ? ? ? if (objs == null || objs.length == 0){
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? for (Object obj : objs) {
? ? ? ? ? ? if (obj instanceof Statement){
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ((Statement) obj).close();
? ? ? ? ? ? ? ? }catch (Exception e){
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (obj instanceof ResultSet){
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ((ResultSet) obj).close();
? ? ? ? ? ? ? ? }catch (Exception e){
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (obj instanceof Connection){
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ((Connection) obj).close();
? ? ? ? ? ? ? ? }catch (Exception e){
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? /**
? ? * @Description 功能描述:將resultSet構(gòu)造為List<Map>
? ? * @Author itdl
? ? * @Date 2022/4/18 21:13
? ? * @Param {@link ResultSet} resultSet
? ? * @Return {@link List < Map <String,Object>>}
? ? **/
? ? private List<LinkedHashMap<String, Object>> buildListMap(ResultSet resultSet) throws SQLException {
? ? ? ? if (resultSet == null) {
? ? ? ? ? ? return Lists.newArrayList();
? ? ? ? }
? ? ? ? List<LinkedHashMap<String, Object>> resultList = new ArrayList<>();
? ? ? ? // 獲取元數(shù)據(jù)
? ? ? ? ResultSetMetaData metaData = resultSet.getMetaData();
? ? ? ? while (resultSet.next()) {
? ? ? ? ? ? // 獲取列數(shù)
? ? ? ? ? ? int columnCount = metaData.getColumnCount();
? ? ? ? ? ? LinkedHashMap<String, Object> map = new LinkedHashMap<>();
? ? ? ? ? ? for (int i = 0; i < columnCount; i++) {
? ? ? ? ? ? ? ? String columnName = metaData.getColumnName(i + 1);
? ? ? ? ? ? ? ? // 過濾掉查詢的結(jié)果包含序號的
? ? ? ? ? ? ? ? if("mm.row_num_01".equalsIgnoreCase(columnName)
? ? ? ? ? ? ? ? ? ? ? ? || "row_num_01".equalsIgnoreCase(columnName)){
? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? // 去除hive查詢結(jié)果的mm.別名前綴
? ? ? ? ? ? ? ? if (columnName.startsWith("mm.")){
? ? ? ? ? ? ? ? ? ? columnName = columnName.substring(columnName.indexOf(".") + 1);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? Object object = resultSet.getObject(columnName);
? ? ? ? ? ? ? ? // maxCompute里面的空返回的是使用\n
? ? ? ? ? ? ? ? if ("\\N".equalsIgnoreCase(String.valueOf(object))) {
? ? ? ? ? ? ? ? ? ? map.put(columnName, "");
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? map.put(columnName, object);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? resultList.add(map);
? ? ? ? }
? ? ? ? return resultList;
? ? }
}
MaxCompute JDBC連接池封裝
MaxCompute 已經(jīng)有了JDBC連接方式 也就是 odbc-jdbc, 最終能夠獲取一個(gè)Connection. 官方文檔:https://help.aliyun.com/document_detail/161246.html
封裝MaxCompute JDBC連接參數(shù)
/**
* @author itdl
* @description maxCompute使用JDBC的連接參數(shù)
* @date 2022/08/08 10:07
*/
@Data
public class MaxComputeJdbcConnParam extends BaseJdbcConnParam{
? ? /**阿里云accessId 相當(dāng)于用戶名 */
? ? private String aliyunAccessId;
? ? /**阿里云accessKey 相當(dāng)于密碼 */
? ? private String aliyunAccessKey;
? ? /** maxcompute_endpoint */
? ? private String endpoint;
? ? /**項(xiàng)目名稱*/
? ? private String projectName;
}
封裝MaxCompute JDBC連接實(shí)現(xiàn)類
就是實(shí)現(xiàn)父類AbstractConnUtil,實(shí)現(xiàn)抽象方法buildConnection
/**
* @Description maxCompute JDBC連接實(shí)現(xiàn)
* @Author itdl
* @Date 2022/08/08 14:26
*/
@Slf4j
public class MaxComputeJdbcUtil extends AbstractConnUtil<MaxComputeJdbcConnParam>{
? ? /**JDBC 驅(qū)動名稱*/
? ? private static final String DRIVER_NAME = "com.aliyun.odps.jdbc.OdpsDriver";
? ? /**
? ? * 構(gòu)造函數(shù), 構(gòu)造工具類對象
? ? *
? ? * @param connParam 連接參數(shù)
? ? */
? ? public MaxComputeJdbcUtil(MaxComputeJdbcConnParam connParam) {
? ? ? ? super(connParam);
? ? }
? ? @Override
? ? protected Connection buildConnection() {
? ? ? ? return buildConn();
? ? }
? ? /**
? ? * 創(chuàng)建連接
? ? * @return 數(shù)據(jù)庫連接
? ? */
? ? private Connection buildConn() {
? ? ? ? try {
? ? ? ? ? ? Class.forName(DRIVER_NAME);
? ? ? ? } catch (ClassNotFoundException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? throw new BizException(ResultCode.MAX_COMPUTE_DRIVE_LOAD_ERR);
? ? ? ? }
? ? ? ? try {
? ? ? ? ? ? Properties dbProperties = new Properties();
? ? ? ? ? ? dbProperties.put("user", connParam.getAliyunAccessId());
? ? ? ? ? ? dbProperties.put("password", connParam.getAliyunAccessKey());
? ? ? ? ? ? dbProperties.put("remarks", "true");
? ? ? ? ? ? // JDBCURL連接模板
? ? ? ? ? ? String jdbcUrlTemplate = "jdbc:odps:%s?project=%s&useProjectTimeZone=true";
? ? ? ? ? ? // 使用驅(qū)動管理器連接獲取連接
? ? ? ? ? ? return DriverManager.getConnection(
? ? ? ? ? ? ? ? ? ? String.format(jdbcUrlTemplate, connParam.getEndpoint(), connParam.getProjectName()), dbProperties);
? ? ? ? } catch (SQLException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? throw new BizException(ResultCode.CONN_USER_PWD_ERR);
? ? ? ? }
? ? }
}
連接測試代碼一起放在結(jié)尾,將會開啟多個(gè)線程獲取連接,然后去獲取表名,表注釋,字段名,字段注釋,傳入page, size和普通sql就可以實(shí)現(xiàn)分頁查詢的封裝方法
Hive JDBC連接池封裝
Hive JDBC連接參數(shù)
Hive連接參數(shù)封裝,除了基礎(chǔ)的JDBC所需字段,還需要kerberos相關(guān)字段,因?yàn)閔ive開啟kerberos認(rèn)證后,需要使用kertab密鑰文件和kbr5.conf配置文件去認(rèn)證。將會在參數(shù)和測試代碼中得到重復(fù)的體現(xiàn)。
/**
* @Description Hive JDBC connection params
* @Author itdl
* @Date 2022/08/10 16:40
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class HiveJdbcConnParam extends BaseJdbcConnParam {
? ? /**
? ? * enable kerberos authentication
? ? */
? ? private boolean enableKerberos;
? ? /**
? ? * principal
? ? */
? ? private String principal;
? ? /**
? ? * kbr5 file path in dick
? ? */
? ? private String kbr5FilePath;
? ? /**
? ? * keytab file path in dick
? ? */
? ? private String keytabFilePath;
}
Hive JDBC獲取連接實(shí)現(xiàn)
Hive獲取JDBC連接之后,本來可以從Connection的元數(shù)據(jù)中獲取表的注釋,但是獲取的中文注釋居然是亂碼,但是我們Hue上查看表注釋又是正常,暫時(shí)沒找到這種方式如何解決,從而退而求其次,通過表名去獲取建表語句,從建表語句中通過正則表達(dá)式提取表的注釋。
/**
* @Description hive connection util
* @Author itdl
* @Date 2022/08/10 16:52
*/
@Slf4j
public class HiveConnUtil extends AbstractConnUtil<HiveJdbcConnParam>{
? ? public HiveConnUtil(HiveJdbcConnParam connParam) {
? ? ? ? super(connParam);
? ? }
? ? /**
? ? * 獲取連接
? ? * @return 連接
? ? */
? ? public Connection getConnection() {
? ? ? ? return connection;
? ? }
? ? @Override
? ? protected Connection buildConnection(){
? ? ? ? try {
//? ? ? ? ? ? Class.forName("org.apache.hive.jdbc.HiveDriver");
? ? ? ? ? ? Class.forName(connParam.getDriverName());
? ? ? ? } catch (ClassNotFoundException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? throw new BizException(ResultCode.HIVE_DRIVE_LOAD_ERR);
? ? ? ? }
? ? ? ? // 開啟kerberos后需要私鑰
? ? ? ? // 拼接jdbcUrl
? ? ? ? String jdbcUrl = "jdbc:hive2://%s:%s/%s";
? ? ? ? String ip = connParam.getIp();
? ? ? ? String port = connParam.getPort() + "";
? ? ? ? String dbName = connParam.getDbName();
? ? ? ? final String username = connParam.getUsername();
? ? ? ? final String password = connParam.getPassword();
? ? ? ? // is enable kerberos authentication
? ? ? ? final boolean enableKerberos = connParam.isEnableKerberos();
? ? ? ? // 格式化
? ? ? ? Connection connection;
? ? ? ? // 獲取連接
? ? ? ? try {
? ? ? ? ? ? Properties dbProperties = new Properties();
? ? ? ? ? ? dbProperties.put("user", username);
? ? ? ? ? ? dbProperties.put("password", password);
? ? ? ? ? ? // 加上remark后, 能夠獲取到標(biāo)注釋 但是會出現(xiàn)中文亂碼
? ? ? ? ? ? dbProperties.put("remarks", "true");
? ? ? ? ? ? if (!enableKerberos) {
? ? ? ? ? ? ? ? jdbcUrl = String.format(jdbcUrl, ip, port, dbName);
? ? ? ? ? ? ? ? connection = DriverManager.getConnection(jdbcUrl, dbProperties);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? final String principal = connParam.getPrincipal();
? ? ? ? ? ? ? ? final String kbr5FilePath = connParam.getKbr5FilePath();
? ? ? ? ? ? ? ? final String secretFilePath = connParam.getKeytabFilePath();
? ? ? ? ? ? ? ? String format = "jdbc:hive2://%s:%s/%s;principal=%s";
? ? ? ? ? ? ? ? jdbcUrl = String.format(format, ip, port, dbName, principal);
? ? ? ? ? ? ? ? // 使用hadoop安全認(rèn)證
? ? ? ? ? ? ? ? System.setProperty("java.security.krb5.conf", kbr5FilePath);
? ? ? ? ? ? ? ? System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
? ? ? ? ? ? ? ? // 解決windows中執(zhí)行可能出現(xiàn)找不到HADOOP_HOME或hadoop.home.dir問題
? ? ? ? ? ? ? ? // Kerberos認(rèn)證
? ? ? ? ? ? ? ? org.apache.hadoop.conf.Configuration conf = new org.apache.hadoop.conf.Configuration();
? ? ? ? ? ? ? ? conf.set("hadoop.security.authentication", "Kerberos");
? ? ? ? ? ? ? ? conf.set("keytab.file", secretFilePath);
? ? ? ? ? ? ? ? conf.set("kerberos.principal", principal);
? ? ? ? ? ? ? ? UserGroupInformation.setConfiguration(conf);
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? UserGroupInformation.loginUserFromKeytab(username, secretFilePath);
? ? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? throw new BizException(ResultCode.KERBEROS_AUTH_FAIL_ERR);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? connection = DriverManager.getConnection(jdbcUrl, dbProperties);
? ? ? ? ? ? ? ? } catch (SQLException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? throw new BizException(ResultCode.KERBEROS_AUTH_SUCCESS_GET_CONN_FAIL_ERR);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? log.info("=====>>>獲取hive連接成功:username:{},jdbcUrl: {}", username, jdbcUrl);
? ? ? ? ? ? return connection;
? ? ? ? } catch (SQLException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? throw new BizException(ResultCode.HIVE_CONN_USER_PWD_ERR);
? ? ? ? } catch (BizException e){
? ? ? ? ? ? throw e;
? ? ? ? }
? ? ? ? catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? throw new BizException(ResultCode.HIVE_CONN_ERR);
? ? ? ? }
? ? }
}
Oracle JDBC連接參數(shù)封裝
只需要繼承父類即可
/**
* @Description Oracle連接的JDBC參數(shù)
* @Author itdl
* @Date 2022/08/15 09:50
*/
public class OracleJdbcConnParam extends BaseJdbcConnParam{
}
Oracle JDBC連接實(shí)現(xiàn)類
包括了普通用戶的認(rèn)證和dba用戶的認(rèn)證
/**
* @Description Oracle獲取jdbc連接工具類
* @Author itdl
* @Date 2022/08/15 09:52
*/
@Slf4j
public class OracleConnUtil extends AbstractConnUtil<OracleJdbcConnParam> {
? ? /**
? ? * 構(gòu)造函數(shù), 構(gòu)造工具類對象
? ? *
? ? * @param connParam 連接參數(shù)
? ? */
? ? public OracleConnUtil(OracleJdbcConnParam connParam) {
? ? ? ? super(connParam);
? ? }
? ? @Override
? ? protected Connection buildConnection() {
? ? ? ? try {
? ? ? ? ? ? Class.forName("oracle.jdbc.driver.OracleDriver");
? ? ? ? } catch (ClassNotFoundException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? throw new BizException(ResultCode.ORACLE_DRIVE_LOAD_ERR);
? ? ? ? }
? ? ? ? // 拼接jdbcUrl
? ? ? ? String jdbcUrl = "jdbc:oracle:thin:@//%s:%s/%s";
? ? ? ? final String ip = connParam.getIp();
? ? ? ? final String port = connParam.getPort() + "";
? ? ? ? final String dbName = connParam.getDbName();
? ? ? ? final String username = connParam.getUsername();
? ? ? ? final String password = connParam.getPassword();
? ? ? ? // 格式化
? ? ? ? jdbcUrl = String.format(jdbcUrl, ip, port, dbName);
? ? ? ? // 獲取連接
? ? ? ? Connection connection;
? ? ? ? try {
? ? ? ? ? ? Properties dbProperties = new Properties();
? ? ? ? ? ? // 用戶名 如果是dba,則后面跟了as sysdba
? ? ? ? ? ? String dba = "as sysdba";
? ? ? ? ? ? dbProperties.put("password", password);
? ? ? ? ? ? dbProperties.put("remarks", "true");
? ? ? ? ? ? if (username.trim().endsWith(dba)) {
? ? ? ? ? ? ? ? dbProperties.put("user", username.trim().substring(0, username.trim().indexOf(dba) - 1));
? ? ? ? ? ? ? ? dbProperties.put("defaultRowPrefetch", "15");
? ? ? ? ? ? ? ? dbProperties.put("internal_logon", "sysdba");
? ? ? ? ? ? ? ? connection = DriverManager.getConnection(jdbcUrl, dbProperties);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? dbProperties.put("user", username);
? ? ? ? ? ? ? ? connection = DriverManager.getConnection(jdbcUrl, dbProperties);
? ? ? ? ? ? }
? ? ? ? ? ? log.info("=====>>>獲取oracle連接成功:username:{}, jdbcUrl: {}", username, jdbcUrl);
? ? ? ? ? ? return connection;
? ? ? ? } catch (SQLException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? if (e.getMessage().contains("TNS:listener")) {
? ? ? ? ? ? ? ? throw new BizException(ResultCode.CONN_LISTENER_UNKNOWN_ERR);
? ? ? ? ? ? }
? ? ? ? ? ? if (e.getMessage().contains("ORA-01017")) {
? ? ? ? ? ? ? ? throw new BizException(ResultCode.CONN_USER_PWD_ERR);
? ? ? ? ? ? }
? ? ? ? ? ? if (e.getMessage().contains("IO 錯(cuò)誤: Got minus one from a read call")) {
? ? ? ? ? ? ? ? throw new BizException(ResultCode.CONN_CONN_TOO_MANY_ERR);
? ? ? ? ? ? }
? ? ? ? ? ? throw new BizException(ResultCode.CONN_UNKNOWN_ERR);
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? throw new BizException(ResultCode.CONN_UNKNOWN_ERR);
? ? ? ? }
? ? }
}
Mysql JDBC連接池封裝
Mysql JDBC連接參數(shù)封裝
只需要繼承父類即可
/**
* @Description Mysql連接的JDBC參數(shù)
* @Author itdl
* @Date 2022/08/15 09:50
*/
public class MysqlJdbcConnParam extends BaseJdbcConnParam{
}
Mysql JDBC連接實(shí)現(xiàn)
需要注意的是連接的屬性里面配置useInformationSchema=true,表示可以直接從Connection中獲取表和字段的注釋。
/**
* @Description Mysql獲取jdbc連接工具類
* @Author itdl
* @Date 2022/08/15 09:52
*/
@Slf4j
public class MysqlConnUtil extends AbstractConnUtil<MysqlJdbcConnParam> {
? ? /**
? ? * 構(gòu)造函數(shù), 構(gòu)造工具類對象
? ? *
? ? * @param connParam 連接參數(shù)
? ? */
? ? public MysqlConnUtil(MysqlJdbcConnParam connParam) {
? ? ? ? super(connParam);
? ? }
? ? @Override
? ? protected Connection buildConnection() {
? ? ? ? try {
? ? ? ? ? ? Class.forName("com.mysql.cj.jdbc.Driver");
? ? ? ? } catch (ClassNotFoundException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? throw new BizException(ResultCode.MYSQL_DRIVE_LOAD_ERR);
? ? ? ? }
? ? ? ? // 拼接jdbcUrl
? ? ? ? String jdbcUrl = "jdbc:mysql://%s:%s/%s?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8";
? ? ? ? final String ip = connParam.getIp();
? ? ? ? final String port = connParam.getPort() + "";
? ? ? ? final String dbName = connParam.getDbName();
? ? ? ? final String username = connParam.getUsername();
? ? ? ? final String password = connParam.getPassword();
? ? ? ? // 格式化
? ? ? ? jdbcUrl = String.format(jdbcUrl, ip, port, dbName);
? ? ? ? // 獲取連接
? ? ? ? try {
? ? ? ? ? ? Properties dbProperties = new Properties();
? ? ? ? ? ? dbProperties.put("user", username);
? ? ? ? ? ? dbProperties.put("password", password);
? ? ? ? ? ? dbProperties.put("remarks", "true");
? ? ? ? ? ? // 設(shè)置可以獲取tables remarks信息
? ? ? ? ? ? dbProperties.setProperty("useInformationSchema", "true");
? ? ? ? ? ? Connection connection = DriverManager.getConnection(jdbcUrl,dbProperties);
? ? ? ? ? ? log.info("=====>>>獲取mysql連接成功:username:{}, jdbcUrl: {}", username, jdbcUrl);
? ? ? ? ? ? return connection;
? ? ? ? } catch (SQLException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? if (e.getMessage().contains("Unknown database")){
? ? ? ? ? ? ? ? throw new BizException(ResultCode.CONN_UNKNOWN_DB_ERR);
? ? ? ? ? ? }
? ? ? ? ? ? throw new BizException(ResultCode.CONN_USER_PWD_ERR);
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? throw new BizException(ResultCode.CONN_UNKNOWN_ERR);
? ? ? ? }
? ? }
}
測試代碼連接各自數(shù)據(jù)庫
@SpringBootTest(classes = DbConnectionDemoApplication.class)
@RunWith(value = SpringRunner.class)
@Slf4j
class DbConnectionDemoApplicationTests {
? ? private DbConnPool<?> connPool = null;
? ? @Test
? ? public void testMysqlConn() throws InterruptedException {
? ? ? ? // 創(chuàng)建連接參數(shù)
? ? ? ? final MysqlJdbcConnParam connParam = new MysqlJdbcConnParam();
? ? ? ? final String ip = "localhost";
? ? ? ? final Integer port = 3306;
? ? ? ? final String username = "root";
? ? ? ? final String password = "root";
? ? ? ? final String dbname = "test_db";
? ? ? ? // 設(shè)置參數(shù)
? ? ? ? connParam.setDriverName(Driver.class.getName());
? ? ? ? connParam.setIp(ip);
? ? ? ? connParam.setPort(port);
? ? ? ? connParam.setUsername(username);
? ? ? ? connParam.setPassword(password);
? ? ? ? connParam.setDbName(dbname);
? ? ? ? // 創(chuàng)建連接池
? ? ? ? connPool = new DbConnPool<>(connParam, 2);
? ? ? ? handler01(dbname, DbDialectEnum.MYSQL);
? ? ? ? new Thread(() -> handler01(dbname, DbDialectEnum.MYSQL)).start();
? ? ? ? new Thread(() -> handler01(dbname, DbDialectEnum.MYSQL)).start();
? ? ? ? Thread.sleep(60 * 1000);
? ? }
? ? @Test
? ? public void testOracleConn() throws InterruptedException {
? ? ? ? // 創(chuàng)建連接參數(shù)
? ? ? ? final OracleJdbcConnParam connParam = new OracleJdbcConnParam();
? ? ? ? final String ip = "你的Oracle的IP地址";
? ? ? ? final Integer port = 1521;
? ? ? ? // 如果是admin賬號 用戶后面+ as sysdba
? ? ? ? final String username = "用戶名";
? ? ? ? final String password = "密碼";
? ? ? ? final String dbname = "實(shí)例/服務(wù)名";
? ? ? ? // 設(shè)置參數(shù)
? ? ? ? connParam.setDriverName(Driver.class.getName());
? ? ? ? connParam.setIp(ip);
? ? ? ? connParam.setPort(port);
? ? ? ? connParam.setUsername(username);
? ? ? ? connParam.setPassword(password);
? ? ? ? connParam.setDbName(dbname);
? ? ? ? // 創(chuàng)建連接池
? ? ? ? connPool = new DbConnPool<>(connParam, 2);
? ? ? ? final DbDialectEnum dbDialectEnum = DbDialectEnum.ORACLE;
? ? ? ? // 處理操作(oracle的schemaName就是用戶名)
? ? ? ? handler01(username, dbDialectEnum);
? ? ? ? // 新建兩個(gè)線程獲取連接
? ? ? ? new Thread(() -> handler01(username, dbDialectEnum)).start();
? ? ? ? new Thread(() -> handler01(username, dbDialectEnum)).start();
? ? ? ? Thread.sleep(60 * 1000);
? ? }
? ? @Test
? ? public void testHiveConn() throws InterruptedException {
? ? ? ? // 創(chuàng)建連接參數(shù)
? ? ? ? final HiveJdbcConnParam connParam = new HiveJdbcConnParam();
? ? ? ? final String ip = "連接的域名";
? ? ? ? final Integer port = 10000;
? ? ? ? // 如果是admin賬號 用戶后面+ as sysdba
? ? ? ? final String username = "賬號@域名";
? ? ? ? final String password = "";
? ? ? ? final String dbname = "數(shù)據(jù)庫名";
? ? ? ? final String principal = "hive/_HOST@域名";
? ? ? ? final String kbr5FilePath = "C:\\workspace\\krb5.conf";
? ? ? ? final String keytabFilePath = "C:\\workspace\\zhouyu.keytab";
? ? ? ? // 設(shè)置參數(shù)
? ? ? ? connParam.setDriverName(Driver.class.getName());
? ? ? ? connParam.setIp(ip);
? ? ? ? connParam.setPort(port);
? ? ? ? connParam.setUsername(username);
? ? ? ? connParam.setPassword(password);
? ? ? ? connParam.setDbName(dbname);
? ? ? ? connParam.setEnableKerberos(true);
? ? ? ? connParam.setPrincipal(principal);
? ? ? ? connParam.setKbr5FilePath(kbr5FilePath);
? ? ? ? connParam.setKeytabFilePath(keytabFilePath);
? ? ? ? // 創(chuàng)建連接池
? ? ? ? connPool = new DbConnPool<>(connParam, 2);
? ? ? ? final DbDialectEnum dbDialectEnum = DbDialectEnum.HIVE;
? ? ? ? // 處理操作(oracle的schemaName就是用戶名)
? ? ? ? handler01(username, dbDialectEnum);
? ? ? ? // 新建兩個(gè)線程獲取連接
? ? ? ? new Thread(() -> handler01(username, dbDialectEnum)).start();
? ? ? ? new Thread(() -> handler01(username, dbDialectEnum)).start();
? ? ? ? Thread.sleep(10 * 60 * 1000);
? ? }
? ? @Test
? ? public void testMaxComputeConn() throws InterruptedException {
? ? ? ? // 創(chuàng)建連接參數(shù)
? ? ? ? final MaxComputeJdbcConnParam connParam = new MaxComputeJdbcConnParam();
? ? ? ? String accessId = "你的阿里云accessId";
? ? ? ? String accessKey = "你的阿里云accessKey";
? ? ? ? String endpoint = "http://service.cn-chengdu.maxcompute.aliyun.com/api";
? ? ? ? String projectName = "項(xiàng)目名=數(shù)據(jù)庫名";
? ? ? ? // 設(shè)置參數(shù)
? ? ? ? connParam.setDriverName(Driver.class.getName());
? ? ? ? connParam.setAliyunAccessId(accessId);
? ? ? ? connParam.setAliyunAccessKey(accessKey);
? ? ? ? connParam.setEndpoint(endpoint);
? ? ? ? connParam.setProjectName(projectName);
? ? ? ? // 創(chuàng)建連接池
? ? ? ? connPool = new DbConnPool<>(connParam, 2);
? ? ? ? final DbDialectEnum dbDialectEnum = DbDialectEnum.MAX_COMPUTE;
? ? ? ? // 處理操作(oracle的schemaName就是用戶名)
? ? ? ? handler01(projectName, dbDialectEnum);
? ? ? ? // 新建兩個(gè)線程獲取連接
? ? ? ? new Thread(() -> handler01(projectName, dbDialectEnum)).start();
? ? ? ? new Thread(() -> handler01(projectName, dbDialectEnum)).start();
? ? ? ? Thread.sleep(60 * 1000);
? ? }
? ? private void handler01(String schemaName, DbDialectEnum dbDialectEnum) {
? ? ? ? final Connection connection = connPool.getConnection();
? ? ? ? // 構(gòu)建工具類
? ? ? ? final SqlUtil sqlUtil = new SqlUtil(connection, dbDialectEnum.getCode());
? ? ? ? // 獲取表和注釋
? ? ? ? final List<TableMetaInfo> tables = sqlUtil.getTables(schemaName);
? ? ? ? log.info("===============獲取所有表和注釋開始===================");
? ? ? ? log.info(tables.toString());
? ? ? ? log.info("===============獲取所有表和注釋結(jié)束===================");
? ? ? ? // 獲取字段和注釋
? ? ? ? final String tableName = tables.get(0).getTableName();
? ? ? ? final List<TableColumnMetaInfo> columns = sqlUtil.getColumnsByTableName(tableName);
? ? ? ? log.info("===============獲取第一個(gè)表的字段和注釋開始===================");
? ? ? ? log.info(columns.toString());
? ? ? ? log.info("===============獲取第一個(gè)表的字段和注釋結(jié)束===================");
? ? ? ? final PageResult<LinkedHashMap<String, Object>> pageResult = sqlUtil.pageQueryMap("select * from " + tableName, 1, 10);
? ? ? ? log.info("===============SQL分頁查詢開始===================");
? ? ? ? log.info("總數(shù):{}", pageResult.getTotal());
? ? ? ? log.info("記錄數(shù):{}", JSONObject.toJSONString(pageResult.getRows()));
? ? ? ? log.info("===============SQL分頁查詢結(jié)束===================");
? ? ? ? connPool.freeConnection(connection);
? ? }
? ? @After
? ? public void close(){
? ? ? ? if (connPool != null){
? ? ? ? ? ? connPool.close();
? ? ? ? ? ? log.info("==================連接池成功關(guān)閉================");
? ? ? ? }
? ? }
}