我是JDBC的新手。我在Centos 6.2上安装了GlassFish 3.1.1,需要将它与连接到另一台服务器上的Oracle 11G数据库的应用程序一起使用。我已经阅读了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/myPWD@192.168.0.1: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/myPWD@192.168.0.1: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");
成为这一行:
DataSource ds = (DataSource)ctext.lookup("jdbc/myDBPool");
它编译没有错误。但现在我很困惑......我们不应该在这里使用OracleDataSource吗?或者,GlassFish以某种方式实现OracleDataSource,因为我确实看到Datasource Classname
的此连接池设置为oracle.jdbc.pool.OracleDataSource
(?)。希望有人能解释一下。
答案 0 :(得分:2)
您的连接池上有ping吗? 如果没有,请检查您的池配置w / http://docs.oracle.com/cd/E18930_01/html/821-2416/beamw.html#beanh
一旦ping工作并配置了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或其他一些数据存储,那么您的代码就是可移植的,不需要任何更改。
答案 1 :(得分:1)
添加cyril的好答案:
您可以使用资源注入来设置DataSource
:
@Resource(name = "jdbc/Your_DB_Res")
private DataSource ds;
启动时,应用程序服务器将注入JDBC ressource。 Java EE Tutorial的This section有更多关于此事的内容。
通过使用资源注入,您可以减少样板代码的数量。 This article介绍了这些概念。
答案 2 :(得分:0)
除了将驱动程序添加到类路径之外,您还应该尝试将appserv-rt.jar文件添加到项目的构建路径中(jar位于Glassfish的lib目录中)。如果您不想包含所有其他jar,首先应创建一个包含appserv-rt jar的库,然后将其添加到项目的构建路径中。