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。
相关推荐
huacuilaifa 2020-10-29
温攀峰 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