mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +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.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>
|
||||||
* 如果需要自定义队列类型,子类重写此方法
|
* 如果需要自定义队列类型,子类重写此方法
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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}
|
||||||
*
|
*
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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