2012-02-26 91 views
1

我是JDBC新手。我在Centos 6.2上安装了GlassFish 3.1.1,需要将它与连接到另一台服务器上的Oracle 11G数据库的应用程序一起使用。我已阅读GlassFish的文档,并认为我了解如何创建JDBC连接池以及JDBC资源。我的问题是,如何在编写java中间层连接到数据库时使用这些信息?在GlassFish中创建JDBC连接池后,如何使用JDBC更改Java代码以访问数据库?

目前(仅使用GlassFish安装而没有JDBC配置),我依靠Java的CentOS环境变量(例如CLASSPATH)来允许Web应用程序使用JDBC驱动程序。不过,我发现了以下错误:

java.lang.NoClassDefFoundError: oracle/jdbc/pool/OracleDataSource 

因此,我试图创建GlassFish中的JDBC连接池和资源(这样应用程序可以使用JDBC驱动程序)。我的Java文件开始了:

import java.sql.*; 
import oracle.jdbc.*; 
import oracle.jdbc.pool.OracleDataSource; 

class JDBCexample { 

    public static void main(String args[]) throws SQLException { 
      Connection conn; 
      Statement stmt; 
      ResultSet rset; 
      String query; 
      String sqlString; 

      String person_firstName; 
      String person_lastName; 
      String person_email; 
      int person_salary; 

      // connect to database 
      OracleDataSource ds = new OracleDataSource(); 
      ds.setURL("jdbc:oracle:thin:myID/[email protected]:1521:mySID"); 
      conn = ds.getConnection(); 

      // read something in database 
      stmt = conn.createStatement(); 
      query = "SELECT first_name, last_name, email, salary FROM HR.Employees where rownum < 6"; 
      rset = stmt.executeQuery(query); 
      while (rset.next()) { 
        person_firstName = rset.getString("first_name"); 
        person_lastName = rset.getString("last_name"); 
        person_email = rset.getString("email"); 
        person_salary = rset.getInt("salary"); 
        System.out.format(person_firstName + " " + person_lastName + " " + person_email + " %d%n", person_salary) 
      } 
and so on... 

问题:如何将改变上面的代码后,我建立一个JDBC连接池(名为:myPool的)和一个JDBC资源(命名为:myDBPool)?如果有问题,我使用Oracle 11.2,CentOS 6.2,GlassFish 3.1.1和mod_jk,并且使用Apache 2.2 webserver JDK 1.6。我没有任何集群或负载平衡。

更新1:我认为this link是一个很好的参考(请参见标题为“创建数据源实例,注册JNDI和连接”一节)。但是,当我修改上面的Java文件,如下所示(只是准备java文件,还没有触及的GlassFish还),

// Add These: 
import javax.naming.Context; 
import javax.naming.InitialContext; 

// Change from this: 
// connect to database 
    OracleDataSource ds = new OracleDataSource(); 
    ds.setURL("jdbc:oracle:thin:myID/[email protected]:1521:mySID"); 
    conn = ds.getConnection(); 

// To this: 
// connect to database 
    Context ctext = new InitialContext(); 
    OracleDataSource ds = (OracleDataSource)ctext.lookup("jdbc/myDBPool"); 
    conn = ds.getConnection(); 

我得到的错误:

JitterClass.java:67: unreported exception javax.naming.NamingException; must be caught or declared to be thrown 
        Context ctext = new InitialContext(); 
            ^
JitterClass.java:68: unreported exception javax.naming.NamingException; must be caught or declared to be thrown 
        OracleDataSource ds = (OracleDataSource)ctext.lookup("jdbc/myDBPool"); 
                     ^

更新2:我清除那些使用下面的cyril的注释编译错误(抛出所有例外)。然后我创建了JDBC连接池和JDBC资源,并且Ping成功。于是我从客户端运行的应用程序,并遵守下列错误:

java.lang.ClassCastException : com.sun.gjc.spi.jdbc40.DataSource40 cannot be cast to oracle.jdbc.pool.OracleDataSource 

在这一点上,如果我添加了include javax.sql.DataSource到程序,并更改该行:

OracleDataSource ds = (OracleDataSource)ctext.lookup("jdbc/myDBPool"); 

成为本line:

DataSource ds = (DataSource)ctext.lookup("jdbc/myDBPool"); 

它编译没有错误。但是现在我感到困惑......我们是不是应该在这里使用OracleDataSource?或者,GlassFish以某种方式实现OracleDataSource,因为我看到Datasource Classname设置为oracle.jdbc.pool.OracleDataSource(?)的连接池的设置。希望有人能解释这一点。

+0

您得到该错误的原因是因为您没有部署JDBC驱动程序,JDBC驱动程序也不是容器类路径的一部分。无论如何,使用JNDI是一个更好的主意,但如果不部署它,它并不会让你使用JDBC驱动程序。 – 2012-02-26 23:44:55

回答

2

在连接池中工作吗? 如果没有,请检查您的池配置W/http://docs.oracle.com/cd/E18930_01/html/821-2416/beamw.html#beanh

一旦坪工作和JDBC资源配置,你应该能够通过JNDI访问它在你的应用程序代码:

InitialContext context = new InitialContext(); 
DataSource ds = (DataSource) context.lookup("jdbc/myDBPool"); // or whatever name you used when creating the resource 
conn = ds.getConnection(); 

希望它能帮助,

对更新1的回应: 这只是编译器告诉你正式捕获或声明可能由JNDI引发的检查异常。 出于测试目的,出了这一点(和喜欢这个未来的错误),最简单的方法是只扩大你的方法签名抛出所有的异常,即:

public static void main(String args[]) throws /*SQL*/Exception { 

响应更新2: 没有理由投除非需要访问JDBC规范中未指定的任何自定义功能,否则JDBC可以与Oracle实现接口。 DataSource的目的是成为Connections的工厂,其API是在JDBC接口中定义的,因此应该是您所需要的。当您在GlassFish中定义连接池和资源时,只要您坚持导入java.sql。*,应用程序服务器就会通过包装JDBC驱动程序类并为您无缝地代理它们来添加值。不需要oracle导入:)主要优点是,如果您以后决定切换到MySQL或其他数据存储,那么您的代码便可以随身携带,不需要任何更改。

+0

感谢您的更新1回应。根据您的建议,现在编译好。谢谢你cyril!请参阅上面的更新2。 – ggkmath 2012-02-27 02:47:09

1

为了增加西里尔很好的答案:

代替JNDI查找,您还可以使用资源注射设置您DataSource

@Resource(name = "jdbc/Your_DB_Res") 
private DataSource ds; 

在启动时,应用程序服务器将注入JDBC资源。 Java EE Tutorial的This section有更多关于此事的信息。

通过使用资源注入,可以减少样板代码的数量。 This article介绍了这些概念。

+0

谢谢TPete。是否有任何重要的优点或缺点以一种方式比另一种方式? – ggkmath 2012-02-27 14:01:27

+0

@ggkmath编辑我的答案,并附上资源注入简介。 – TPete 2012-02-27 14:53:02

0

除了将驱动程序添加到类路径之外,还应该尝试将appserv-rt.jar文件添加到项目的构建路径(该jar位于Glassfish的lib目录中)。如果您不想包含所有其他jar,则应首先创建一个包含appserv-rt jar的库,然后将其添加到项目的构建路径中。