mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix pool bug
This commit is contained in:
parent
efa7d433af
commit
cbaf8103e9
@ -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>
|
||||
* 如果需要自定义队列类型,子类重写此方法
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,15 @@ public class DSPool implements Closeable {
|
||||
return this.factory.getDataSourceName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据源工厂
|
||||
*
|
||||
* @return 数据源工厂
|
||||
*/
|
||||
public DSFactory getFactory() {
|
||||
return this.factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自定义的{@link DSFactory}
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user