我是否正确使用了Java PooledConnections?

12

我想在Java中使用连接池(因为每个线程创建一个连接的成本很高),所以我正在使用MysqlConnectionPoolDataSource()对象。我跨线程保留我的数据源。因此,我像这样在整个应用程序中仅使用一个数据源:

  startRegistry();    // creates an RMI registry for MySQL
  MysqlConnectionPoolDataSource dataSource = new MysqlConnectionPoolDataSource();
  dataSource.setUser("username");
  dataSource.setPassword("password");
  dataSource.setServerName("serverIP");
  dataSource.setPort(3306);
  dataSource.setDatabaseName("dbname");

  InitialContext context = createContext();   // Creates a context
  context.rebind("MySQLDS", dataSource);

现在我已经创建了我的数据源,在每个独立的线程中,我正在执行以下操作:

  PooledConnection connect = dataSource.getPooledConnection();
  Connection sqlConnection = connect.getConnection();

  Statement state = sqlConnection.createStatement();

  ResultSet result = state.executeQuery("select * from someTable");
  // Continue processing results

我猜想我对dataSource.getPooledConnection();的调用感到困惑。

这真的是在获取池化连接吗? 这个过程线程安全吗? 我注意到PooledConnection有像notify()和wait()这样的方法......这意味着它可能没有做我认为它在做的事情...

此外,何时以及如何释放连接?

我在想是否自己编写会更有益,因为那样我就更熟悉所有内容,但在这种情况下,我真的不想重复造轮子:)

谢谢SO


所有的Java类都有notify和wait方法,因为它们被继承自java.lang.Object。尽管如此,实际上使用它们的情况非常少见。 - Matthew Flaschen
是的,我对Java有点新手哈哈... 我正在尝试一下。 - Polaris878
这是来自Apache DBCP的一个示例:http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/doc/PoolingDataSourceExample.java?view=co - Koray Tugay
1个回答

15

这不是正确的方式。数据源需要由您运行应用程序的容器进行管理。 MysqlConnectionPoolDataSource 不是连接池,它只是 javax.sql.DataSource 接口的具体实现。通常情况下,您可以在 JNDI 上下文中定义它并从那里获取它。此外,MySQL 在他们的文档中明确说明了这一切。

现在,如何使用它取决于应用程序的目的。如果它是 Web 应用程序,则需要参考特定 servlet 容器/应用服务器的 JNDI 资源文档。例如 Tomcat,则可以在这里找到它:here。如果您正在运行客户端应用程序 - 对于这种情况,我非常怀疑连接池的价值 - 那么您需要寻找一个可以利用 MySQL 提供的连接池数据源的连接池框架,例如 C3P0

您发布的代码的另一个问题是 PooledConnection#getConnection() 将返回底层连接,因此它不是池化连接。在其上调用 close() 方法将不会将连接返回到池中,而只是真正地关闭它。池必须每次创建新的连接。

接下来讲讲线程安全的问题,这取决于使用的实际连接池框架。C3P0已经证明了其在这方面的强韧性,只要您按照标准惯用法编写JDBC代码,即仅使用JDBC接口并在最短的范围内获取和关闭所有资源(ConnectionStatementResultSet),您就不用担心它。


2
奇怪的回答。“数据源需要由任何容器管理” - 不,没有任何数据源“需要”由任何容器管理。它可以,但不需要。引入一个容器只是为了拥有连接池是不合理的。要手动添加连接池,我建议使用Apache Commons DBCP(就像Tomcat本身所做的那样),或者尝试Tomcat的JDBC池(在版本7中作为Commons DBCP的替代品实现得更快)。 - mvmn
1
@mvmn: "无论您在哪个容器中运行应用程序"。简单来说,这是指Servlet容器/ Web服务器/应用服务器(Tomcat、Glassfish、JBoss AS、WebSphere AS等)。 - BalusC
3
@BalusC:并没有改变我所说的内容——没有必要拥有一个容器来使DataSource成为池化的。没有必要,好吗?无论是Servlet容器还是其他什么容器,都不重要,不需要将独立应用程序转换为Web应用程序或添加类似Spring的东西,只需使用C3P0即可。在我看来,“使用C3P0”比实际“答案”更好。 - mvmn
1
@BalusC 他想说的是,“你可以在独立的Java应用程序中拥有一个池化数据源,一个不在容器中运行的Java应用程序”。我认为他说得有道理,如果你更新一下你的答案会更好。 - Koray Tugay
1
偶然发现这个问题,我真的觉得@BalusC的答案有点误导人。首先,我同意mvmn的观点-仅为了拥有Pooled Connections而合并任何Java EE complaince(或类似内容)服务器,确实是一个巨大的开销。其次,BalusC强调,“MysqlConnectionPoolDataSource只是DataSource的具体实现,与连接池无关”,但我认为这是错误的。如果它只是另一种实现,为什么作者要称之为**MysqlConnectionPoolDataSource**呢?还有其他的实现,比如XADataSource - Giorgi Tsiklauri
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接