diff --git a/src/main/java/org/apache/ibatis/datasource/pooled/PooledDataSource.java b/src/main/java/org/apache/ibatis/datasource/pooled/PooledDataSource.java index 49274fbee72..a76a0747c63 100644 --- a/src/main/java/org/apache/ibatis/datasource/pooled/PooledDataSource.java +++ b/src/main/java/org/apache/ibatis/datasource/pooled/PooledDataSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2024 the original author or authors. + * Copyright 2009-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -389,11 +389,10 @@ private int assembleConnectionTypeCode(String url, String username, String passw } protected void pushConnection(PooledConnection conn) throws SQLException { - lock.lock(); try { - state.activeConnections.remove(conn); if (conn.isValid()) { + state.activeConnections.remove(conn); if (state.idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == expectedConnectionTypeCode) { state.accumulatedCheckoutTime += conn.getCheckoutTime(); @@ -441,17 +440,19 @@ private PooledConnection popConnection(String username, String password) throws while (conn == null) { lock.lock(); try { - if (!state.idleConnections.isEmpty()) { - // Pool has available connection - conn = state.idleConnections.remove(0); - if (log.isDebugEnabled()) { - log.debug("Checked out connection " + conn.getRealHashCode() + " from pool."); - } - } else if (state.activeConnections.size() < poolMaximumActiveConnections) { - // Pool does not have available connection and can create a new connection - conn = new PooledConnection(dataSource.getConnection(), this); - if (log.isDebugEnabled()) { - log.debug("Created connection " + conn.getRealHashCode() + "."); + if (state.activeConnections.size() < poolMaximumActiveConnections) { + if (!state.idleConnections.isEmpty()) { + // Pool has available connection + conn = state.idleConnections.remove(0); + if (log.isDebugEnabled()) { + log.debug("Checked out connection " + conn.getRealHashCode() + " from pool."); + } + } else { + // Pool does not have available connection and can create a new connection + conn = new PooledConnection(dataSource.getConnection(), this); + if (log.isDebugEnabled()) { + log.debug("Created connection " + conn.getRealHashCode() + "."); + } } } else { // Cannot create new connection diff --git a/src/test/java/org/apache/ibatis/datasource/pooled/PooledDataSourceTest.java b/src/test/java/org/apache/ibatis/datasource/pooled/PooledDataSourceTest.java index f80a7e7ccf5..bd310d740b2 100644 --- a/src/test/java/org/apache/ibatis/datasource/pooled/PooledDataSourceTest.java +++ b/src/test/java/org/apache/ibatis/datasource/pooled/PooledDataSourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2023 the original author or authors. + * Copyright 2009-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -158,4 +158,27 @@ void forceCloseAllShouldRemoveAllActiveAndIdleConnection() throws SQLException { assertEquals(0, poolState.getActiveConnectionCount()); assertEquals(0, poolState.getIdleConnectionCount()); } + + @Test + void shouldActiveConnectionLessThanOrEqualPoolMaximumActiveConnections() throws Exception { + dataSource.setPoolMaximumCheckoutTime(1000); + dataSource.setPoolTimeToWait(500); + dataSource.setPoolMaximumActiveConnections(1); + dataSource.setPoolMaximumIdleConnections(1); + + Connection conn1 = dataSource.getConnection(); + conn1.setAutoCommit(false); + Connection conn2 = dataSource.getConnection(); + conn2.setAutoCommit(false); + conn1.close(); + Connection conn3 = dataSource.getConnection(); + conn3.setAutoCommit(false); + conn2.close(); + Connection conn4 = dataSource.getConnection(); + conn4.setAutoCommit(false); + PoolState poolState = dataSource.getPoolState(); + assertTrue(poolState.activeConnections.size() <= poolState.dataSource.poolMaximumActiveConnections); + conn3.close(); + conn4.close(); + } }