Unverified Commit efde8fd4 authored by t1mon's avatar t1mon Committed by GitHub
Browse files

Refactor BaseDataSource and unified handling of JDBC resource releases. (#2184)

* Refactor BaseDataSource.isConnectable().

* Add BaseDataSource test.

* Unified handling of JDBC resource releases.

* Fix sonar check error.

* Remove useless logger.

* Refactor BaseDataSource.getJdbcUrl().

* Modify ConnectionUtils.releaseResource().

* Add javadoc

* Remove useless method.

* Add BaseDataSourceTest UT
parent d83a94a3
Loading
Loading
Loading
Loading
+26 −77
Original line number Diff line number Diff line
@@ -16,86 +16,35 @@
 */
package org.apache.dolphinscheduler.common.utils;

import java.util.Arrays;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;

public class ConnectionUtils {

  public static final Logger logger = LoggerFactory.getLogger(ConnectionUtils.class);

	private static ConnectionUtils instance;

	ConnectionUtils() {
	}

	public static ConnectionUtils getInstance() {
		if (null == instance) {
			syncInit();
		}
		return instance;
	}

	private static synchronized void syncInit() {
		if (instance == null) {
			instance = new ConnectionUtils();
		}
	}

	public void release(ResultSet rs, Statement stmt, Connection conn) {
		try {
			if (rs != null) {
				rs.close();
				rs = null;
			}
		} catch (SQLException e) {
			logger.error(e.getMessage(),e);
		} finally {
			try {
				if (stmt != null) {
					stmt.close();
					stmt = null;
				}
			} catch (SQLException e) {
				logger.error(e.getMessage(),e);
			} finally {
				try {
					if (conn != null) {
						conn.close();
						conn = null;
					}
				} catch (SQLException e) {
					logger.error(e.getMessage(),e);
				}
			}
		}
  private ConnectionUtils() {
    throw new IllegalStateException("ConnectionUtils class");
  }

	public static void releaseResource(ResultSet rs, PreparedStatement ps, Connection conn) {
		ConnectionUtils.getInstance().release(rs,ps,conn);
		if (null != rs) {
			try {
				rs.close();
			} catch (SQLException e) {
				logger.error(e.getMessage(),e);
			}
		}
  /**
   * release resource
   * @param resources resources
   */
  public static void releaseResource(AutoCloseable... resources) {

		if (null != ps) {
			try {
				ps.close();
			} catch (SQLException e) {
				logger.error(e.getMessage(),e);
			}
    if (resources == null || resources.length == 0) {
      return;
    }

		if (null != conn) {
    Arrays.stream(resources).filter(Objects::nonNull)
        .forEach(resource -> {
          try {
				conn.close();
			} catch (SQLException e) {
            resource.close();
          } catch (Exception e) {
            logger.error(e.getMessage(), e);
          }
		}
        });
  }
}
+2 −8
Original line number Diff line number Diff line
@@ -18,10 +18,10 @@ package org.apache.dolphinscheduler.dao;

import com.alibaba.druid.pool.DruidDataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.dolphinscheduler.common.enums.DbType;
import org.apache.dolphinscheduler.common.utils.ConnectionUtils;
import org.apache.dolphinscheduler.dao.entity.MonitorRecord;
import org.apache.dolphinscheduler.dao.utils.MysqlPerformance;
import org.apache.dolphinscheduler.dao.utils.PostgrePerformance;
@@ -63,13 +63,7 @@ public class MonitorDBDao {
        }catch (Exception e) {
            logger.error("SQLException: {}", e.getMessage(), e);
        }finally {
            try {
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                logger.error("SQLException ", e);
            }
            ConnectionUtils.releaseResource(conn);
        }
        return monitorRecord;
    }
+6 −29
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package org.apache.dolphinscheduler.dao;
import org.apache.dolphinscheduler.common.Constants;
import org.apache.dolphinscheduler.common.enums.TaskRecordStatus;
import org.apache.dolphinscheduler.common.utils.CollectionUtils;
import org.apache.dolphinscheduler.common.utils.ConnectionUtils;
import org.apache.dolphinscheduler.common.utils.DateUtils;
import org.apache.dolphinscheduler.common.utils.StringUtils;
import org.apache.dolphinscheduler.dao.entity.TaskRecord;
@@ -170,7 +171,7 @@ public class TaskRecordDao {
        } catch (SQLException e) {
            logger.error("Exception ", e);
        }finally {
            closeResource(rs, pstmt, conn);
            ConnectionUtils.releaseResource(rs, pstmt, conn);
        }
        return count;
    }
@@ -255,7 +256,7 @@ public class TaskRecordDao {
        } catch (SQLException e) {
            logger.error("Exception ", e);
        }finally {
            closeResource(rs, pstmt, conn);
            ConnectionUtils.releaseResource(rs, pstmt, conn);
        }
        return recordList;
    }
@@ -292,28 +293,4 @@ public class TaskRecordDao {

        }
    }

    private static void closeResource(ResultSet rs, PreparedStatement pstmt, Connection conn) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                logger.error("Exception ", e);
            }
        }
        if (pstmt != null) {
            try {
                pstmt.close();
            } catch (SQLException e) {
                logger.error("Exception ", e);
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                logger.error("Exception ", e);
            }
        }
    }
}
+104 −5
Original line number Diff line number Diff line
@@ -16,10 +16,21 @@
 */
package org.apache.dolphinscheduler.dao.datasource;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.apache.dolphinscheduler.common.enums.DbType;
import org.apache.dolphinscheduler.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * data source base class
 */
public abstract class BaseDataSource {

  private static final Logger logger = LoggerFactory.getLogger(BaseDataSource.class);

  /**
   * user name
   */
@@ -57,17 +68,105 @@ public abstract class BaseDataSource {
  public void setPrincipal(String principal) {
    this.principal = principal;
  }

  /**
   * test whether the data source can be connected successfully
   * @throws Exception
   * @return driver class
   */
  public abstract void isConnectable() throws Exception;
  public abstract String driverClassSelector();

  /**
   * @return db type
   */
  public abstract DbType dbTypeSelector();

  /**
   * gets the JDBC url for the data source connection
   * @return
   */
  public abstract String getJdbcUrl();
  public String getJdbcUrl() {
    StringBuilder jdbcUrl = new StringBuilder(getAddress());

    appendDatabase(jdbcUrl);
    appendPrincipal(jdbcUrl);
    appendOther(jdbcUrl);

    return jdbcUrl.toString();
  }

  /**
   * append database
   * @param jdbcUrl jdbc url
   */
  private void appendDatabase(StringBuilder jdbcUrl) {
    if (dbTypeSelector() == DbType.SQLSERVER) {
      jdbcUrl.append(";databaseName=").append(getDatabase());
    } else {
      if (getAddress().lastIndexOf('/') != (jdbcUrl.length() - 1)) {
        jdbcUrl.append("/");
      }
      jdbcUrl.append(getDatabase());
    }
  }

  /**
   * append principal
   * @param jdbcUrl jdbc url
   */
  private void appendPrincipal(StringBuilder jdbcUrl) {
    boolean tag = dbTypeSelector() == DbType.HIVE || dbTypeSelector() == DbType.SPARK;
    if (tag && StringUtils.isNotEmpty(getPrincipal())) {
      jdbcUrl.append(";principal=").append(getPrincipal());
    }
  }

  /**
   * append other
   * @param jdbcUrl jdbc url
   */
  private void appendOther(StringBuilder jdbcUrl) {
    if (StringUtils.isNotEmpty(getOther())) {
      String separator = "";
      switch (dbTypeSelector()) {
        case CLICKHOUSE:
        case MYSQL:
        case ORACLE:
        case POSTGRESQL:
          separator = "?";
          break;
        case DB2:
          separator = ":";
          break;
        case HIVE:
        case SPARK:
        case SQLSERVER:
          separator = ";";
          break;
        default:
          logger.error("Db type mismatch!");
      }
      jdbcUrl.append(separator).append(getOther());
    }
  }

  /**
   * test whether the data source can be connected successfully
   */
  public void isConnectable() {
    Connection con = null;
    try {
      Class.forName(driverClassSelector());
      con = DriverManager.getConnection(getJdbcUrl(), getUser(), getPassword());
    } catch (ClassNotFoundException | SQLException e) {
      logger.error("Get connection error: {}", e.getMessage());
    } finally {
      if (con != null) {
        try {
          con.close();
        } catch (SQLException e) {
          logger.error(e.getMessage(), e);
        }
      }
    }
  }

  public String getUser() {
    return user;
+7 −40
Original line number Diff line number Diff line
@@ -17,59 +17,26 @@
package org.apache.dolphinscheduler.dao.datasource;

import org.apache.dolphinscheduler.common.Constants;
import org.apache.dolphinscheduler.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.apache.dolphinscheduler.common.enums.DbType;

/**
 * data source of ClickHouse
 */
public class ClickHouseDataSource extends BaseDataSource {
    private static final Logger logger = LoggerFactory.getLogger(ClickHouseDataSource.class);

    /**
     * gets the JDBC url for the data source connection
     * @return
     * @return driver class
     */
    @Override
    public String getJdbcUrl() {
        String jdbcUrl = getAddress();
        if (jdbcUrl.lastIndexOf('/') != (jdbcUrl.length() - 1)) {
            jdbcUrl += "/";
        }

        jdbcUrl += getDatabase();

        if (StringUtils.isNotEmpty(getOther())) {
            jdbcUrl += "?" + getOther();
        }

        return jdbcUrl;
    public String driverClassSelector() {
        return Constants.COM_CLICKHOUSE_JDBC_DRIVER;
    }

    /**
     * test whether the data source can be connected successfully
     * @throws Exception
     * @return db type
     */
    @Override
    public void isConnectable() throws Exception {
        Connection con = null;
        try {
            Class.forName(Constants.COM_CLICKHOUSE_JDBC_DRIVER);
            con = DriverManager.getConnection(getJdbcUrl(), getUser(), getPassword());
        } finally {
            if (con != null) {
                try {
                    con.close();
                } catch (SQLException e) {
                    logger.error("ClickHouse datasource try conn close conn error", e);
                }
            }
        }

    public DbType dbTypeSelector() {
        return DbType.CLICKHOUSE;
    }
}
Loading