/** * Constructor: 創建一個Connection Pool * * @param databaseUrl * The connection url * @param userName * user name * @param password * password * @param maxSize * max size of the connection pool */ publicMySQLConnectionPool(String databaseUrl, String userName, String password, int maxSize) { this.databaseUrl = databaseUrl; this.userName = userName; this.password = password; this.maxPoolSize = maxSize; }
/** * Get an available connection * * @return An available connection * @throws SQLException * Fail to get an available connection */ publicsynchronized Connection getConnection()throws SQLException { Connectionconn=null;
// 沒辦法在建立新的連線 (已達到最大連線數) if (isFull()) { thrownewSQLException("The connection pool is full."); }
// 有些database一段時間沒使用會自動斷連線,所以我們可以確認一下從freePool取出的connection是否還有連線著 // For Azure Database for MySQL, if there is no action on one connection for some // time, the connection is lost. By this, make sure the connection is // active. Otherwise reconnect it. conn = makeAvailable(conn); return conn; }
/** * 這邊注意的是,要使用synchronized才會把singleton的object lock住,確保不會有多個thread同時還回去多個connection * client使用完,要還回去Pool中 * * Return a connection to the pool * * @param conn * The connection * @throws SQLException * When the connection is returned already or it isn't gotten * from the pool. */ publicsynchronizedvoidreturnConnection(Connection conn) throws SQLException { // 如果conn是空的,表示client沒有使用connection,因此不需要回傳 if (conn == null) { thrownewNullPointerException(); } // 檢查 conn 是否在 occupiedPool 中,並且可以從 occupiedPool 中移除,如果不是,則拋出 SQLException if (!occupiedPool.remove(conn)) { thrownewSQLException( "The connection is returned already or it isn't for this pool"); } // 如果沒跳Exception則已經從occupied移除,可以放回 freePool 中 freePool.push(conn); }
/** * 也要使用synchronized,確保資源被lock住,以正確做檢查freePool是否已經塞滿 * * Verify if the connection is full. * * @return if the connection is full */ privatesynchronizedbooleanisFull() { return ((freePool.size() == 0) && (connNum >= maxPoolSize)); }
/** * 因為connection必須是singleton才不會無謂的一直建立資源 * 因此有一個private的constructor,確保只有透過getInstance()才能取得實例 * * Create a connection for the pool * * @return the new created connection * @throws SQLException * When fail to create a new connection. */ private Connection createNewConnectionForPool()throws SQLException { Connectionconn= createNewConnection(); connNum++; occupiedPool.add(conn); return conn; }
/** * 創建連線,必須是private,確保只有透過createNewConnectionForPool()才能取得實例 * * Crate a new connection * * @return the new created connection * @throws SQLException * When fail to create a new connection. */ private Connection createNewConnection()throws SQLException { Connectionconn=null; conn = DriverManager.getConnection(databaseUrl, userName, password); return conn; }
/** * 從freePool中取出一個連線,並且放入occupiedPool * * Get a connection from the pool. If there is no free connection, return * null * * @return the connection. */ private Connection getConnectionFromPool() { // 先reset Connectionconn=null; // 如果有空閒的連線,就從freePool中取出,並且放入佔用中的occupiedPool if (freePool.size() > 0) { conn = freePool.pop(); occupiedPool.add(conn); } // 回傳連線 return conn; }
/** * 檢查連線是否還連線著,如果沒有則重新連線 * * Make sure the connection is available now. Otherwise, reconnect it. * * @param conn * The connection for verification. * @return the available connection. * @throws SQLException * Fail to get an available connection */ private Connection makeAvailable(Connection conn)throws SQLException {
// 透過下Query來確認連線是否還連線著 if (isConnectionAvailable(conn)) { return conn; }
/** * 確認一下目前連線是否還連線著,可以透過下Query來確認 * * By running a sql to verify if the connection is available * * @param conn * The connection for verification * @return if the connection is available for now. */ privatebooleanisConnectionAvailable(Connection conn) { try (Statementst= conn.createStatement()) { st.executeQuery(SQL_VERIFYCONN); returntrue; } catch (SQLException e) { returnfalse; } } // Just an Example publicstaticvoidmain(String[] args)throws SQLException { Connectionconn=null; // 建立資源池 MySQLConnectionPoolpool=newMySQLConnectionPool( "jdbc:mysql://mysqlaasdevintic-sha.cloudapp.net:3306/<Your DB name>", "<Your user>", "<Your Password>", 2); try { // 取得連線 conn = pool.getConnection();
If you use the spring-boot-starter-jdbc or spring-boot-starter-data-jpa “starters”, you automatically get a dependency to HikariCP.
org.springframework.jdbc.datasource.SimpleDriverDataSource 查看他的API說明文件可以發現上面寫NOTE: This class is not an actual connection pool; it does not actually pool Connections表示:這個類別並不是真正的Connection Pool,他並不會真的去做Connection Pool的動作。