fix pool bug

This commit is contained in:
Looly 2024-11-12 13:40:07 +08:00
parent efa7d433af
commit cbaf8103e9
7 changed files with 76 additions and 31 deletions

View File

@ -20,6 +20,7 @@ import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.pool.ObjectFactory;
import org.dromara.hutool.core.pool.ObjectPool;
import org.dromara.hutool.core.pool.Poolable;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.thread.ThreadUtil;
import java.io.IOException;
@ -117,6 +118,12 @@ public class PartitionObjectPool<T> implements ObjectPool<T> {
IoUtil.closeQuietly(this.partitions);
}
@Override
public String toString() {
return StrUtil.format("PartitionObjectPool: total: {}, idle: {}, active: {}",
getTotal(), getIdleCount(), getActiveCount());
}
/**
* 创建阻塞队列默认为{@link ArrayBlockingQueue}<br>
* 如果需要自定义队列类型子类重写此方法

View File

@ -81,7 +81,7 @@ public class PoolPartition<T> implements ObjectPool<T> {
// 检查是否超过最长空闲时间
final long maxIdle = this.config.getMaxIdle();
if (maxIdle <= 0 || poolable.getIdle() <= maxIdle) {
return poolable.getRaw();
return obj;
}
}
@ -188,11 +188,7 @@ public class PoolPartition<T> implements ObjectPool<T> {
return wrapPoolable(t);
}
@SuppressWarnings("unchecked")
private Poolable<T> wrapPoolable(final T t) {
if (t instanceof Poolable) {
return (Poolable<T>) t;
}
return new PartitionPoolable<>(t, this);
}

View File

@ -105,6 +105,15 @@ public class DSPool implements Closeable {
return this.factory.getDataSourceName();
}
/**
* 获取数据源工厂
*
* @return 数据源工厂
*/
public DSFactory getFactory() {
return this.factory;
}
/**
* 设置自定义的{@link DSFactory}
*

View File

@ -120,6 +120,7 @@ public class DSUtil {
* @param dsFactory 数据源工厂
* @return 自定义的数据源工厂
*/
@SuppressWarnings("resource")
public static DSFactory setGlobalDSFactory(final DSFactory dsFactory) {
DSPool.getInstance().setFactory(dsFactory);
return dsFactory;

View File

@ -16,14 +16,13 @@
package org.dromara.hutool.db.ds.pooled;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.pool.Poolable;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.db.DbException;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.setting.props.Props;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
@ -33,23 +32,21 @@ import java.util.Properties;
*
* @author Looly
*/
public class PooledConnection extends ConnectionWrapper implements Poolable<Connection> {
public class PooledConnection extends ConnectionWrapper {
private final PooledDataSource dataSource;
private long lastBorrow = System.currentTimeMillis();
private boolean isClosed = false;
/**
* 构造
*
* @param config 数据库配置
* @param config 数据库配置
* @param dataSource 数据源
*/
public PooledConnection(final ConnectionConfig<?> config, final PooledDataSource dataSource) {
// issue#IA6EUQ 部分驱动无法自动加载此处手动完成
final String driver = config.getDriver();
if(StrUtil.isNotBlank(driver)){
if (StrUtil.isNotBlank(driver)) {
try {
Class.forName(driver);
} catch (final ClassNotFoundException e) {
@ -74,9 +71,9 @@ public class PooledConnection extends ConnectionWrapper implements Poolable<Conn
}
try {
if(null != dataSource.driver){
if (null != dataSource.driver) {
this.raw = dataSource.driver.connect(config.getUrl(), info);
}else{
} else {
this.raw = DriverManager.getConnection(config.getUrl(), info);
}
} catch (final SQLException e) {
@ -86,6 +83,11 @@ public class PooledConnection extends ConnectionWrapper implements Poolable<Conn
this.dataSource = dataSource;
}
/**
* 归还连接<br>
* 关闭操作在池中的意义为使用完毕归还到池中<br>
* 如果想彻底关闭连接请使用{@link #destroy()}方法
*/
@Override
public void close() {
this.isClosed = true;
@ -97,13 +99,11 @@ public class PooledConnection extends ConnectionWrapper implements Poolable<Conn
return this.isClosed;
}
@Override
public long getLastReturn() {
return lastBorrow;
}
@Override
public void setLastReturn(final long lastReturn) {
this.lastBorrow = lastReturn;
/**
* 销毁连接即彻底关闭并丢弃连接
*/
public void destroy() {
this.isClosed = true;
IoUtil.closeQuietly(this.raw);
}
}

View File

@ -46,7 +46,7 @@ public class PooledDataSource extends AbstractDataSource {
protected Driver driver;
private final int maxWait;
private final ObjectPool<Connection> connPool;
private final ObjectPool<PooledConnection> connPool;
/**
* 构造
@ -83,8 +83,8 @@ public class PooledDataSource extends AbstractDataSource {
}
@Override
public Connection getConnection() throws SQLException {
return (Connection) connPool.borrowObject();
public PooledConnection getConnection() throws SQLException {
return connPool.borrowObject();
}
@Override
@ -112,15 +112,15 @@ public class PooledDataSource extends AbstractDataSource {
* @param config 数据库配置
* @return {@link ObjectFactory}
*/
private ObjectFactory<Connection> createConnFactory(final ConnectionConfig<?> config) {
return new ObjectFactory<Connection>() {
private ObjectFactory<PooledConnection> createConnFactory(final ConnectionConfig<?> config) {
return new ObjectFactory<PooledConnection>() {
@Override
public Connection create() {
public PooledConnection create() {
return new PooledConnection(config, PooledDataSource.this);
}
@Override
public boolean validate(final Connection connection) {
public boolean validate(final PooledConnection connection) {
try {
return null != connection
&& connection.isValid(maxWait);
@ -133,8 +133,10 @@ public class PooledDataSource extends AbstractDataSource {
}
@Override
public void destroy(final Connection connection) {
IoUtil.closeQuietly(connection);
public void destroy(final PooledConnection connection) {
if(null != connection){
connection.destroy();
}
}
};
}

View File

@ -0,0 +1,30 @@
package org.dromara.hutool.db.ds;
import org.dromara.hutool.db.DbException;
import org.dromara.hutool.db.config.SettingConfigParser;
import org.dromara.hutool.db.ds.pooled.PooledDSFactory;
import org.dromara.hutool.setting.Setting;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.sql.SQLException;
public class PooledDataSourceTest {
@Test
void getConnTest() {
final DSPool dsPool = new DSPool(
new SettingConfigParser(new Setting("config/db.setting")),
new PooledDSFactory());
final DSWrapper test = dsPool.getDataSource("test");
Assertions.assertEquals("org.dromara.hutool.db.ds.pooled.PooledDataSource", test.getRaw().getClass().getName());
for (int i = 0; i < 1000; i++) {
try {
test.getConnection().close();
} catch (final SQLException e) {
throw new DbException(e);
}
}
}
}