关于实现 javax.sql.ConnectionPoolDataSource

因为一些业务需要修改了jdbc驱动程序
改成如下形式的驱动 和获得connect的方法

[code="java"]Java code
Class.forName("com.jlins.xxxLogonDriver");
Properties prop = new Properties();
prop.setProperty("user", "user1");
prop.setProperty("password", "pass1");
Connection connecton = DriverManager.getConnection("xxx:xxx:@ip:port:frist:second", prop)[/code]

已经校验通过,在jdbc直接连接或者tomcat下配置jndi都能通过。
在配置websphere的时候就有麻烦了,websphere使用的是 javax.sql.ConnectionPoolDataSource 类创建jdbc 提供者,
而我们目前并没有新建 javax.sql.ConnectionPoolDataSource 的实例,想问一下如何 ConnectionPoolDataSource到底做了什么?如何实现?

3个回答

连接池
在基础DataSource实现中,客户端Connection对象和物理数据库连接是1:1对应的关系。当Connection对象关闭时,物理连接也被丢弃。因此,在每个客户会话中都会带来打开、初始化和关闭物理连接的过度使用。
连接池通过维护一个物理数据库连接存贮区,解决了这个问题。它可以被客户会话反复使用。连接池极大的提高了性能和可伸缩性,尤其在三层环境中多客户端或以 共享较小的物理数据库连接数。图11-1,JDBC驱动提供了一个ConnectionPoolDataSource实现,应用服务器可以用来建立和管理 连接池。

用来管理连接池的算法是专门实现的而且随着应用服务器的不同而不同。应用服务器提供给客户端一个DataSource接口实现,使得连接池对客户端是透明的。结果,相比以前同样使用JNDI和DataSourceAPI,客户端获得更好的性能和伸缩性。

下面各节介绍ConnectionPoolDataSource接口、PooledConnection接口和 ConnectionEvent类。这些接口和类在客户端使用的DataSource和Connection接口下运作。我们将一步一步地描述它们组合成 一个典型的连接池实现。本章还将描述一些基础DataSource对象和连接池实现的重要区别。另外,将讨论一个池中的连接怎样维护一池的可重用 PrepredStatement对象。

虽然本章中多数的讨论均假设在三层环境中,连接池在二层环境中也很有用。在二层环境中,JDBC驱动同时实现DataSource和ConnectionPoolDataSource接口。该实现受宜于连接池,允许应用程序打开和关闭多个连接。

11.1 ConnectionPoolDataSource?和PooledConnection
一般地,JDBC驱动实现ConnectionPoolDataSource接口,应用服务器使用它来获取PooledConnection对象。例11-1显示两个版本的getPooledConnection方法。

public interface ConnectionPoolDataSource {PooledConnection getPooledConnection() throws SQLException;PooledConnection getPooledConnection(String user, String password) throws SQLException;...}CODE EXAMPLE 11-1 The ConnectionPoolDataSource interface一个PooledConnection对象代表一个与数据源的物理连接。JDBC驱动实现PooledConnection对象封装了所有维护该连接的细节。

应用服务器通过其实现的DataSource接口,存贮和重用PooledConnection对象。当客户端调用 DataSource.getConnection方法。应用服务器使用物理PooledConnection对象来获取逻辑Connection对象。 例11-2显示PooledConnection接口定义。

public interface PooledConnection {Connection getConnection() throws SQLException;void close() throws SQLException;
void addConnectionEventListener(ConnectionEventListener listener);
void addStatementEventListener(StatementEventListener listener);
void removeConnectionEventListener(ConnectionEventListener listener);
void removeStatementEventListener(StatementEventListener listener);}
CODE EXAMPLE 11-2 The PooledConnection interface
当应用服务器使用完一个连接,它会用Connection.close方法关闭逻辑连接。这会关闭逻辑连接但不会关闭物理连接,物理连接返回到池这样就可以被重用。

连接池对客户端是完全透明的:一个客户获取一个池连接并使用该连接和它获取和使用非池连接一样。

11.2 连接事件
上面曾提到,当一个应用调用Connection.close方法时,底层物理连接——PooledConnection对象——就可以重用了。JavaBean风格的事件被用来通知连接池管理器(应用服务器)PooledConnection对象可以被循环使用。
为了对PooledConnection对象通知事件,连接池管理器必须实现ConnectionEventListener接口并注册成 PooledConnection对象的监听器。ConnectionEventListener接口定义了如下两个方法,它们对应两种可以在 PooledConnection对象中出现的事件。

•connectionClosed——当与PooledConnection对象关联的逻辑Connection对象关闭,即应用程序调用Connection.close方法时,该事件触发。
•connectionErrorOccurred——当致命错误发生,如服务器崩溃,导致连接丢失,触发该事件。
连接池管理器把自身注册为一个PooledConnection对象的监听器,使用 PooledConnection.addConnectionEventListener方法。一般地,在返回给应用程序Connection对象之 前,连接池管理器把自身注册为一个ConnectionEventListener。

当相应事件发生时,驱动调用ConnectionEventListener对象的connectionClosed和 connectionErrorOccurred方法。两个方法都以ConnectionEvent对象为参数,这样可以用来决定哪个 PooledConnection对象被关闭或出错。当JDBC应用程序关闭其逻辑连接,JDBC驱动通过调用监听器实现的方法 connectionClosed来通知连接池管理器(监听器)。从这点来看,连接池管理器会返回PooledConnection对象给连接池以进行重 用。

当错误发生时,JDBC驱动通过调用connectionErrorOccurred方法通知监听器,之后抛出一个 SQLException对象给应用程序以告知同样的错误。遇到致命错误的时候,出现问题的PooledConnection对象不会返回给连接池。相 反,连接池管理器会调用PooledConnection对象的PooledConnection.close方法来关闭物理连接。

11.3 三层环境的连接池
如下各步列示当JDBC客户端向实现连接池的DataSource对象请求一个连接时,发生何事:

•客户端调用DataSource.getConnection
•应用服务器提供DataSource实现,在其连接池中寻找是否有合适的PooledConnection对象——一个物理数据库连接——可用。决定 PooledConnection对象合适否,包括匹配用户确认信息或应用类型使用其它专有实现规范。lookup方法和其它与管理连接池有关的方法与特 定应用服务器有关。
•如果没有合适的PooledConnection对象可用,应用服务器调用 ConnectionPoolDataSource.getPooledConnection方法以获得新的物理连接。JDBC驱动实现 ConnectionPoolDataSource以创建一个新的PooledConnection对象并返回给应用服务器。
•不考虑PooledConnection是否来自于连接池或新创建的,应用服务器有内部记录来显示物理连接正在被使用。
•应用服务器调用PooledConnection.getConnection来获得一个逻辑Connection对象。该逻辑Connection对象 实际上是一个物理PooledConnection对象的“句柄”。当连接池生效时,通过DataSource.getConnection方法返回该句 柄。
•应用服务器通过调用PooledConnection.addConnectionEventListener方法把自己注册为一个ConnectionEventLisner。这样当物理连接可以重用时,应用服务器会被通知到。
•在基础DataSource事例中使用相同的Connection API时,逻辑Connection对象会返回给JDBC客户。注意,指定的物理连接不能被重用,直到客户端调用Connection.close方法。
连接池也可以在两层环境下实现,那里没有应用服务器。这时,JDBC驱动同时提供客户端可见的DataSource实现和指定的ConnectionPoolDataSource实现。

11.4 DataSource?实现和连接池
除了提高性能和可伸缩性以外,JDBC应用看不出在获取DataSource对象来实现连接池和不获取之间有任何不同。然而,在应用服务器和驱动级实现之间有一些重要的区别。
一个基础DataSource实现,没有实现连接池,典型的,由JDBC驱动厂商提供。在基础DataSource实现中,下面的是真实的:

•DataSource?.getConnection方法创建一个新的Connection对象,来代表一个物理连接并封装对该连接的所有安装和管理工作。
•Connection.close方法关闭物理连接并释放相关资源。
在包括连接池的DataSource实现中,在幕后有一系列重大事件发生。在如上实现中,下面的是真实的:

•DataSource?实现包括一个实现的指定连接池模块会管理一缓冲区的PooledConnection对象。DataSource对象典型的由应用服务器实现作为一层在驱动实现ConnectionPoolDataSource和PooledConnection接口的顶层。
•DataSource?.getConnection 调用PooledConnection.getConnection方法来获得一个指定物理连接的逻辑句柄。只有当连接池中没有可用的连接时,才会出现建 立新物理连接的花费。当需要一个新的物理连接时,连接池管理器会调用ConnectionPoolDataSource的 getPooledConnection方法来创建一个。管理物理连接的工作由PooledConnection对象代理。
•Connection.close方法关闭逻辑句柄,但物理连接还存在。连接池管理器被通知指定的PooledConnection对象现在可以重用了。如果应用程序试图重用逻辑句柄,Connection实现会抛出一个SQLException。
•单一一个物理PooledConnection对象会在生命期内产生许多逻辑Connection对象。对一个给定的PooledConnection对 象,只有最新生成的逻辑Connection对象才有效。当相关的PooledConnection.getConnection被调用时,任何先前存在 的Connection对象会被自动关闭。监听器(连接池管理器)不会被通知该事件。
•一个连接池管理器通过调用PooledConnection.close方法关闭物理连接。该方法典型的只有在特定环境下被调用:当应用服务器遇到正常的关闭,当连接缓冲区正在被重新初始化,或者当应用服务器收到一个事件指出连接出现一个无法恢复的错误时。
11.5 部署
部署一个实现了连接池的DataSource对象需要一个客户端可见的DataSource对象和一个底层ConnectionPoolDataSource对象。该对象被注册成一个基于JNDI的命名服务。
第一步是部署ConnectionPoolDataSource实现,如例11-3所示:

// ConnectionPoolDS implements the ConnectionPoolDataSource// interface. Create an instance and set properties.com.acme.jdbc.ConnectionPoolDS cpds =new com.acme.jdbc.ConnectionPoolDS();
cpds.setServerName(“bookserver”);
cpds.setDatabaseName(“booklist”);
cpds.setPortNumber(9040);
cpds.setDescription(“Connection pooling for bookserver”);
// Register the ConnectionPoolDS with JNDI, using the logical name// “jdbc/pool/bookserver_pool”
Context ctx = new InitialContext();
ctx.bind(“jdbc/pool/bookserver_pool”, cpds);
CODE EXAMPLE 11-3 Deploying a ConnectionPoolDataSource object一旦该步完成,ConnectionPoolDataSource实现就可做为客户可见的DataSource实现的基础。DataSource实现的部署和ConnectionPoolDataSource实现一样,如列11-4所示:

// PooledDataSource implements the DataSource interface.
// Create an instance and set properties.com.acme.appserver.PooledDataSource ds =new com.acme.appserver.PooledDataSource();
ds.setDescription(“Datasource with connection pooling”);
// Reference the previously registered ConnectionPoolDataSourceds.setDataSourceName(“jdbc/pool/bookserver_pool”);
// Register the DataSource implementation with JNDI, using the logical// name “jdbc/bookserver”.
Context ctx = new InitialContext();
ctx.bind(“jdbc/bookserver”, ds);
CODE EXAMPLE 11-4 Deploying a DataSource object backed by aConnectionPoolDataSource objectDataSource?对象现在已在应用中可用。

11.6 连接池的声明重用
JDBC 3.0说明书中介绍了池声明的特征。该特征允许应用程序和重用连接一样,重用PreparedStatement对象。通过连接池该特征可以实现。
图11-2展示了池中PreparedStatement对象如何与PooledConnection对象关联的逻辑视图。通过PooledConnection对象,PreparedStatement对象可以被多个逻辑连接以透明的方式重用。

在图11-2中,连接池和声明池通过应用程序实现。不过,该功能也可以被驱动或底层数据源实现。对声明池的说明意味着以上任何一种实现都是被允许的。

11.6.1 使用池化的声明
如果一个池化连接要重用声明,该重用必须对应用程序完全透明。换句话说,从应用程序的角度来看,使用PreparedStatement对象加入声明池和单独使用它一样。声明保持打开以使在下面可以撤底的重用。声明池的唯一可见效果是性能的提升。
应用程序可以通过调用DatabaseMetaData的supportsStatementPooling方法,找出数据源是否支持声明池。如果返回值为true,应用程序可以选择使用正在被池化的PreparedStatement对象。

很多时候,重用声明是一种重大的优化。这在复杂的准备声明中尤其有效。然而,它也会被注明使大量声明保持开放会对源的使用有反面的影响。

11.6.2 关闭池化的声明
应用程序关闭池化声明和关闭非池化的声明一样。不论是否池化,声明被关闭后就不再对应用可用,并且任何重用的企图都会导致抛出例外。

下面的方法可以关闭一个池化声明:

•Statement.close——应用程序调用;如果声明已经池化,会关闭应用程序使用的逻辑声明但不会关闭池化的物理声明
•Connection.close——应用程序调用
◦非池化的连接——关闭物理连接和所有该连接创建的声明。这很重要因为垃圾收集机制对探测何时外部管理资源可以被释放无效。
◦池化的连接——关闭逻辑连接和它返回的逻辑声明,但不关闭底层的PooledConnection对象和与其相关的池化声明。
•PooledConnection?.closeAll——连接池管理器调用,关闭所有通过PooledConnection池化的物理声明。
应用程序不能直接关闭已池化的物理声明;它通过连接池管理来完成。PooledConnection.closeAll方法关闭所有通过给定物理连接打开的声明,并释放与这些声明相关联的资源。
应用程序也不能直接控制已池化的声明。一个声明池与一个PooledConnection对象相关联。它的行为受ConnectionPoolDataSource对象产生的属性决定。11.7“ConnectionPoolDataSource属性”讨论这些属性。

11.7 ConnectionPoolDataSource?属性
对DataSource接口,JDBC API定义了一系列属性用于配置连接池的行为。表11-1显示各属性:

连接池设置属性遵从JavaBeans规范中JavaBeans组件规定的协议。连接池厂商可以选择增加该集合以实现特定的属性。这样,附加的属性必须命名与标准属性名不冲突。

像DataSource实现一样,ConnectionPoolDataSource实现必须提供每个支持属性的getter和 setter方法。这些属性一般在ConnectionPoolDataSource对象部署的时候初始化。例11-5显示了一个厂商实现 ConnectionPoolDataSource接口的setting属性。

VendorConnectionPoolDS vcp = new VendorConnectionPoolDS();
vcp.setMaxStatements(25);vcp.setInitialPoolSize(10);
vcp.setMinPoolSize(1);vcp.setMaxPoolSize(0);vcp.setMaxIdleTime(0);
vcp.setPropertyCycle(300);
CODE EXAMPLE 11-5 Setting connection pool configuration propertiesConnectionPoolDataSource?对象的属性集应用它创建的PooledConnection对象。应用服务器管理一个PooledConnection对象池,使用这些属性来决定如何管理该池。

ConnectionPoolDataSource?配置属性并不是直接访问JDBC客户端。管理工具需要操作ConnectionPoolDataSource实现的属性,可以通过内省的方式来访问这些属性。

B_yellow
青乡 你的答案是哪本书上的内容么?能告诉一下么?
5 年多之前 回复
B_yellow
青乡 你的答案是哪本书上的内容么?能告诉一下么?
5 年多之前 回复

这个连接池
大概的实现就是,有个计数器,然后有个map
在启动时候创建用户配置允许的多个数据库连接放到map里面,计数器为用户配置允许的最大连接数,然后你每拿一个Connection 计数器都减1,你销毁一个就+1
当然这些都是必须是同步的、线程安全的synchronized

你的jdbc驱动,在proxool连接池,或者hibernate下能正常吗?(我是指在tomcat上)

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问