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

View File

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

View File

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

View File

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

View File

@ -16,14 +16,13 @@
package org.dromara.hutool.db.ds.pooled; 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.map.MapUtil;
import org.dromara.hutool.core.pool.Poolable;
import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.db.DbException; import org.dromara.hutool.db.DbException;
import org.dromara.hutool.db.config.ConnectionConfig; import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.setting.props.Props; import org.dromara.hutool.setting.props.Props;
import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Properties; import java.util.Properties;
@ -33,11 +32,9 @@ import java.util.Properties;
* *
* @author Looly * @author Looly
*/ */
public class PooledConnection extends ConnectionWrapper implements Poolable<Connection> { public class PooledConnection extends ConnectionWrapper {
private final PooledDataSource dataSource; private final PooledDataSource dataSource;
private long lastBorrow = System.currentTimeMillis();
private boolean isClosed = false; private boolean isClosed = false;
/** /**
@ -86,6 +83,11 @@ public class PooledConnection extends ConnectionWrapper implements Poolable<Conn
this.dataSource = dataSource; this.dataSource = dataSource;
} }
/**
* 归还连接<br>
* 关闭操作在池中的意义为使用完毕归还到池中<br>
* 如果想彻底关闭连接请使用{@link #destroy()}方法
*/
@Override @Override
public void close() { public void close() {
this.isClosed = true; this.isClosed = true;
@ -97,13 +99,11 @@ public class PooledConnection extends ConnectionWrapper implements Poolable<Conn
return this.isClosed; return this.isClosed;
} }
@Override /**
public long getLastReturn() { * 销毁连接即彻底关闭并丢弃连接
return lastBorrow; */
} public void destroy() {
this.isClosed = true;
@Override IoUtil.closeQuietly(this.raw);
public void setLastReturn(final long lastReturn) {
this.lastBorrow = lastReturn;
} }
} }

View File

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