Hibernate之默认连接池
这个问题的主要思考主要源自于测试系统的一个问题,应用运行几个小时之后,就报出了数据库连接关闭问题。起初分析一段最近改动过的代码如下:
Connection conn = null;
ConnectionProvider cp = null;
try{
cp = 获取连接池类,这里代码因***原因,不能写出来,望见谅
conn = cp.getConnection();
.....
}finally{
cp.closeConnection(conn);
}起初根据这段代码。分析是否连接池中的连接都已经关闭,那么从连接池中获取的关闭连接,就无法使用了,这只是猜想,代码和微测试是检验真理的唯一标准(还有一种方式就是找大神),进行Hibernate连接池源码分析。
1、hibernate可以使用C3P0这种第三方提供的连接池,当然不进行配置的话,Hibernate也会默认提供一个连接池:DriverManagerConnectionProvider
//连接池,为一个arrayList
private final ArrayList pool;
//连接池大小
private int poolSize;
//构造函数,创建ArrayList对象
public DriverManagerConnectionProvider()
{
this.pool = new ArrayList();
this.checkedOut = 0;
}
//获取连接方法
public Connection getConnection()
throws SQLException
{
if (log.isTraceEnabled()) log.trace("total checked-out connections: " + this.checkedOut);
//从连接池获取连接,哇,这里居然用到了同步,每次获取连接池中的数据库连接都要加锁,看来Hibernate默认数据库连接不适合高并发场景。还有Hibernate真实连接大小可以超过默认poolSize
synchronized (this.pool) {
//连接池不为空,则从连接池中获取
if (!(this.pool.isEmpty())) {
int last = this.pool.size() - 1;
if (log.isTraceEnabled()) {
log.trace("using pooled JDBC connection, pool size: " + last);
this.checkedOut += 1;
}
Connection pooled = (Connection)this.pool.remove(last);
if (this.isolation != null) pooled.setTransactionIsolation(this.isolation.intValue());
if (pooled.getAutoCommit() != this.autocommit) pooled.setAutoCommit(this.autocommit);
return pooled;
}
}
//连接池为空,则创建新的连接并返回
log.debug("opening new JDBC connection");
Connection conn = DriverManager.getConnection(this.url, this.connectionProps);
if (this.isolation != null) conn.setTransactionIsolation(this.isolation.intValue());
if (conn.getAutoCommit() != this.autocommit) conn.setAutoCommit(this.autocommit);
if (log.isDebugEnabled()) {
log.debug("created connection to: " + this.url + ", Isolation Level: " + conn.getTransactionIsolation());
}
if (log.isTraceEnabled()) this.checkedOut += 1;
return conn;
}
//哈哈,这里就是closeConnection方法,可以看到,当前连接池大小如果小于poolSize(poolSize默认20),则会把该连接放入池中,否则,关闭连接
public void closeConnection(Connection conn) throws SQLException
{
if (log.isDebugEnabled()) this.checkedOut -= 1;
synchronized (this.pool) {
int currentSize = this.pool.size();
if (currentSize < this.poolSize) {
if (log.isTraceEnabled()) log.trace("returning connection to pool, pool size: " + (currentSize + 1));
this.pool.add(conn);
return;
}
}
log.debug("closing JDBC connection");
conn.close();
}经过分析,可以得出
1、closeConnection方法,只有当当前连接池大小如果小于poolSize(poolSize默认20),则会把该连接放入池中,否则,关闭连接。所以,猜想关闭的连接放入连接池中是错误的。
2、连接池的获取连接和关闭连接,都需要对连接池(pool)加锁,则默认连接池大小不适合高并发场景。
3、Hibernate真实连接大小可以超过默认poolSize。
相关推荐
温攀峰 2020-08-17
幸运小侯子 2020-08-14
dongCSDN 2020-06-28
一恍过去 2020-06-26
qingmuluoyang 2020-06-26
jameszgw 2020-06-25
Rain 2020-06-25
MissFuTT 2020-06-16
标题无所谓 2020-06-14
xclxcl 2020-06-13
onlypersevere 2020-06-13
dongCSDN 2020-06-09
llltaotao 2020-06-03
GavinZhera 2020-06-03
langyue 2020-05-31
牧场SZShepherd 2020-05-27
geek00 2020-05-27
zhaolisha 2020-05-16