论坛首页 入门技术论坛

使用数据库连接池connection.close()不是真正关闭的疑问

浏览 14739 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-04-09   最后修改:2009-04-10
引发几个疑问啊。
问题1:
使用数据库连接池得到的connection是不用程序关闭,连接池自己会把一定时间内没有使用的connection拿回到池里。----然后,我不知道这句话对不对。如果对,那么在spring中,hibernate中,很多都用了ThreadLocal来控制多线程中的事务,这样不会就有问题了吗?---连接池把con分给这个线程使用,放在ThreadLocal中,而一回收后又交给其他线程使用,放在ThreadLocal中,要是这些线程同时要做事务,同一个connection那还如何事务?

问题2:
人家都说调用connection的close()方法没关系,不会被关,怎么不会被关啊?
sun api文档方法说明:
引用
void close()
          Releases this Connection object's database and JDBC resources immediately instead of waiting for them to be automatically released.

如果我没理解错,调用此方法是主动去释放这个连接的资源,以代替数据库或者jdbc自动释放,不就是关闭吗?
除非是从数据库连接池里get到的connection是经过包装的。
比如
class MyConnection extends java.sql.Connection
{
@override
 public void close()
 {
   //回收到连接池里
 }
}

而连接池的代码,得到connection实际是它的子类MyConnection
class ConnectionPool ..
{
 ...
 public Conncetion getConnection()
 {
   return new MyConnection(...);
  }
 ...
}
硬是把close方法重写了,这样调用close时就不会被真正关闭。
我懒人一个,没去看开源的数据库连接池代码。不知以上的观点对不对,或者还有其他机制,或者我想得根本不对!
有人知道其真正原理吗?能讨论下原理吗?
   发表时间:2009-04-09  
如果使用连接池的话,
调用connection.close()是通知连接池回收该connection,不进行关闭操作。所以就回到池里了。关闭操作,由连接池在一定条件下执行的。
连接池自己维护创建新链接、关闭长期不用链接等等。
0 请登录后投票
   发表时间:2009-04-09  
metadmin 写道
如果使用连接池的话,
调用connection.close()是通知连接池回收该connection,不进行关闭操作。所以就回到池里了。关闭操作,由连接池在一定条件下执行的。
连接池自己维护创建新链接、关闭长期不用链接等等。

谢谢楼上的回答,不过我想知道的是你说的这个“通知连接池”是怎么样实现的?
0 请登录后投票
   发表时间:2009-04-09  
连接池重写了Connectin.close()方法。

close方法,是将该Cnnection回收连接池,而不是关闭。

呵呵,我说的“通知”词语不恰当。
0 请登录后投票
   发表时间:2009-04-09  
metadmin 写道
连接池重写了Connectin.close()方法。

close方法,是将该Cnnection回收连接池,而不是关闭。

呵呵,我说的“通知”词语不恰当。

真和我想的一样啊?真是这样,就剩下不知道第一个问题的答案了。
0 请登录后投票
   发表时间:2009-04-10   最后修改:2009-04-10
问题2,我想的那个是一个实现方式。
网上找到
使用JAVA中的动态代理实现数据库连接池
,它也是转自ibm的资料,估计这个是更标准的实现方式,采用了有人叫Business Delegate模式,也有人叫动态代理模式实现。
这种模式,在我blog上有介绍
代理模式
现在就问题1没找到答案了。
0 请登录后投票
   发表时间:2009-04-13  
问题1啊,等得好苦
0 请登录后投票
   发表时间:2009-04-20   最后修改:2009-04-20
对于问题2,我的理解是:

    楼主有没有想过 其实连接池也就是对象池的一种,只不过是涉及到数据库操作而已,所谓“关闭”,也就是把暂时不用的“连接对象”放回“池子”里。当发生某些“事务”(比如很久不连接或者连接数达到上限)时,再做真正的关闭操作。

对于问题1,我的理解是:

引用
要是这些线程同时要做事务,同一个connection那还如何事务?

我没有完全明白是什么意思?
本来ThreadLocal就是轻量线程同步机制吧,只不过是对于某个成员变量(如这里的con),它让每个线程都拥有一个con的副本,这样为什么会出现问题呢?楼主能说详细点么?

引用
一回收后又交给其他线程使用


这里我有个模糊的地方,ThreadLocal是的con副本,这里还涉及不涉及回收的问题?

1,如果涉及,那么也应该是回收到池子里

2,我的理解是回收之后不会直接给其他线程使用,而是从“池中”拿一个con对象给其他线程使用。这里相当于有个“中介机构”
0 请登录后投票
   发表时间:2009-04-20  
看代理模式
0 请登录后投票
   发表时间:2009-04-20  
对不起,我对问题1没说得清楚。我再解释一下些问题:
线程ThreadA取得一个AConnection去做操作,因为要涉及事务,ThreadLocal保存了关于这个ThreadA的con,下次此线程再需要con去做操作时,ThreadLocal就直接把这个保存的con给ThreadA了。
一段时间过去了
连接池发现这个AConnection很久没用,就回收了。
现在有个线程ThreadB需要一个Connnection去做操作,连接池给它分配了刚刚回收的AConnection
ThreadB拿AConnection去做事情
此时ThreadA也醒来,采用AConnection去做事情
一个Connection被两个线程同时使用,事务就可能出问题了。因为同一个Connection是去执行事务的前提。

突然,我在描述问题时,想到了,其实spring或者hibernate或者其他什么的,在回收某个线程的Con时,同时会把ThreadLocal里与它对应的con变为空,此线程在下次取Con时发现con==null,它就又去连接池里取了。
于是问题1也有解决方案了。呵呵。
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics