Tomcat和JDBC连接池

11

我正在尝试使用Tomcat建立与MySQL数据库的连接池。我的简单应用程序名为Projekt,在Apache/conf/Catalina/localhost下的Projekt.xml中:

<Context docBase="Projekt.war" path="/Projekt">
  <Resource name="jdbc/mysqldb"
      auth="Container"
  factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
      type="javax.sql.DataSource"
      driverClassName="com.mysql.jdbc.Driver"
      url="jdbc:mysql://localhost:3306/Music"
      username="andrzej"
      password="qazxsw"
      maxActive="20"
      maxIdle="30"
      maxWait="5"
  />
</Context> 

我的应用程序的web.xml

<servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>org.jtp.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/Hai</url-pattern>
</servlet-mapping>

<resource-ref>     
        <description>DB Connection</description>     
       <res-ref-name>jdbc/mysqldb</res-ref-name>     
       <res-type>javax.sql.DataSource</res-type>     
       <res-auth>Container</res-auth>     
 </resource-ref>

在我的Apache/lib文件夹中,我有

mysql-connector-java-5.1.18-bin.jar

但是当我执行这段代码时:

Context initContext  = new InitialContext();
dataSource = (DataSource)initContext.lookup("java:comp/env/jdbc/mysqldb");
System.out.println(dataSource.getConnection().createStatement().
            execute("select * from Users"));

我遇到了异常。
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'

我现在感到困惑,在一些地方,我读到可能是由于没有将驱动程序放置在tomcat/lib中引起的,但我已经将其放置并且它也工作正常,因为当我使用手动连接测试驱动程序时它可以正常工作。

对于我的设置,我试图遵循http://people.apache.org/~fhanik/jdbc-pool/jdbc-pool.html

编辑: 最终解决了,似乎是我在一个文件中有一些剩余的上下文标签,因此在解析时覆盖了其他属性,所以最终问题出在我自己身上。

2个回答

16
为了在Tomcat中实现JDBC连接池,有一种替代XML配置文件的方法。我从来没有能够让那些Contextresource-ref标签起作用。此外,如果你不真正需要JNDI功能,那么这些标签就是过度设计。
另一种选择是使用Java代码来配置Tomcat的JDBC连接池。请参阅Tomcat 7文档页面中“普通Java”部分的示例代码,The Tomcat JDBC Connection Pool
基本上,你需要:
  1. 实例化PoolProperties对象以存储您的设置(数据库URL、数据库用户名、数据库密码等)。
  2. 实例化Tomcat DataSource对象,同时传递步骤#1中的PoolProperties对象。

非常简单。像这样...

PoolProperties p = new PoolProperties();
p.setUrl( jdbc:postgresql://localhost:5432/" + "my_database_name" );
p.setDriverClassName( "org.postgresql.Driver" );
p.setUsername( "someUserName" );
p.setPassword( "somePassword" );
…
DataSource datasource = new org.apache.tomcat.jdbc.pool.DataSource( p );
datasource.setPoolProperties(p);

使用数据源...

Connection conn = null;
try {
    conn = datasource.getConnection();

DataSource实例可以存储在以下位置:


这太棒了。谢谢。 - PhoenixPerson

13

看起来你缺少了 Context envCtx = (Context) initCtx.lookup("java:comp/env");
应该这样执行JNDI查找:

// Obtain our environment naming context
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");

// Look up our data source
DataSource ds = (DataSource) envCtx.lookup("jdbc/EmployeeDB");

// Allocate and use a connection from the pool
Connection conn = ds.getConnection(); 

来自http://tomcat.apache.org/tomcat-7.0-doc/jndi-resources-howto.html的文档。


@drobson:当从Java类访问数据源时,DataSource类型是什么?我使用的是org.apache.tomcat.jdbc.pool.DataSource,或者应该是javax.sql.DataSource(后者是Resource的type属性的值)? - Sefran2
@Cricket:org.apache.tomcat.jdbc.pool.DataSource很好,因为它实现了javax.sql.DataSource。当您将资源类型设置为javax.sql.DataSource时,您实际上是在说您将使用实现javax.sql.DataSource的对象。 - drobson
@drobson:谢谢。所以我可以使用其中一个。我能在执行查询的类中调用查找吗?还是有更好的方法?现在,我在执行任何一组查询之前都会调用查找,但我不知道“连接过多”错误是由此引起的,还是原因是context.xml配置。 - Sefran2
@Cricket,你想要每个数据源只有一个实例。例如,在整个应用程序中,您只需要一个EmployeeDB数据源。我个人更喜欢使用Spring来解耦所有的DAO,并将数据源的一个实例注入到它们中。另一种方法是在会话中查找数据源,然后在DAO中使用会话中的getter引用数据源。但是!!!我建议研究一下解耦模式!! - drobson
@drobson:如果我为数据源使用单例模式,你觉得怎么样? - Sefran2
显示剩余5条评论

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