下面具体介绍一下数据源和Javax.sql.DataSource接口。在数据源中存储了所有建立数据库连接的信息。就象通过指定文件名你可以在文件系统中找到文件一样,通过提供正确的数据源名称,你可以找到相应的数据库连接。javax.sql.DataSource接口定义了如 何实现数据源。在该接口中定义了九个属性。表一列出了对这些属性的描述。由于本文是以8i为例,在8i中没有实现roleName属性,所以在表中没有对此属性做描述。 表一:数据源标准属性 属性名称 属性数据类型 描述 databaseName String 数据库名称,即数据库的SID。 dataSourceName String 数据源接口实现类的名称。 description String 对数据源的描述。 networkProtocol String 和服务器通讯使用的网络协议名。在8i中,该属性只在使用OCI驱动程序时有效,缺省协议是TCP协议。 passWord String 用户登录密码。 portNumber Int 数据库服务器使用的端口,缺省值为1521。 serverName String 数据库服务器名称。 user String 用户登录名。 在javax.sql.DataSource接口中定义了以下方法: * public synchronized void setDatabaseName(String dbname) * public synchronized String getDatabaseName() * public synchronized void setDataSourceName(String dsname) * public synchronized String getDataSourceName() * public synchronized void setDescription(String desc) * public synchronized String getDescription() * public synchronized void setNetworkProtocol(String np) * public synchronized String getNetworkProtocol() * public synchronized void setPassword(String pwd) * public synchronized void setPortNumber(int pn) * public synchronized int getPortNumber() * public synchronized void setServerName(String sn) * public synchronized String getServerName() * public synchronized void setUser(String user) * public synchronized String getUser() 通过这些方法,程序员可以获得建立连接需要的所有信息。需要注重的是,程序员不可以获取登陆密码,这就在一定程度上保证了安全性。需要注重的另一点是所有的方法都是synchronized方法,这是为了保证应用程序的线程安全(Thread-safe)。假如在调用 该方法时,即使数据源实例发生变化不会影响程序的正确运行。 除了实现由SUN定义的属性和方法外,8i还提供了自己的数据源属性和方法。这些方法和 属性是在Oracle.jdbc.pool.DataSource中实现的。 8i扩展数据源属性如表二所示: 表二: 属性名称 属性数据类型 描述 driverType String 使用的 JDBC驱动程序的类型,包括oci8, thin和kprb url String 数据库连接的URL。 tnsEntry String TNS条目名称 在oracle.jdbc.pool.DataSource中除了实现javax.sql.DataSource接口中定义的方法外 ,还实现了以下方法: * public synchronized void setDriverType(String dt) * public synchronized String getDriverType() * public synchronized void setURL(String url) * public synchronized String getURL() * public synchronized void setTNSEntryName(String tns) * public synchronized String getTNSEntryName() 同时,DataSource还实现了java.io.Serializable和javax.naming.Referenceable接口 。 独立使用数据源实际应用中,你可以把DataSource注册到JNDI,也可以单独使用。下面先给出一个单独 使用DataSource的例子: // 初始化数据源实例 DataSource ods = new DataSource(); ods.setDriverType("thin"); ods.setServerName("Chicago"); ods.setNetworkProtocol("tcp"); ods.setDatabaseName("chidb"); ods.setPortNumber(1521); ods.setUser("guest"); ods.setPassword("guest"); // 从数据源中获取数据库连接 Connection conn = ods.getConnection(); // 通过数据库连接进行数据操作 ……………… 使用DataSource时有几点需要注重: 假如使用的时服务器端内部驱动程序(server-side internal driver),driverType属 性会被设置为kprb,其它所有属性失效。 假如使用Thin或OCI驱动程序: URL中可以包括用户登录名和用户登录密码。例如: jdbcracle:thin:guest/guest@Chicago:1521:chidb; 假如设定了url属性,tnsEntry, driverType, portNumber, networkProtocol, server Name,和databaseName属性将失效。 在没有设定url属性的情况下,假如设定了tnsEntry属性,portNumber, networkProtoc ol, serverName,和databaseName属性将失效。 假如使用OCI驱动程序,并且networkProtocol属性被设定为ipc,除user和password外的 所有其他属性将失效。 通过JNDI使用数据源在本节首先给出了一个实际程序,然后通过程序来讲解如何通过JNDI查询数据源。 import java.sql.*; import javax.sql.*; import oracle.jdbc.driver.*; import oracle.jdbc.pool.DataSource; import javax.naming.*; import javax.naming.spi.*; import java.util.Hashtable; public class DataSourceJNDI { public static void main (String args []) throws SQLException { // 初始化名称服务环境 Context ctx = null; try { Hashtable env = new Hashtable (5); env.put (Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); env.put (Context.PROVIDER_URL, "file:JNDI"); ctx = new InitialContext(env); } catch (NamingException ne) { ne.printStackTrace(); } bind(ctx, "jdbc/chidb"); lookup(ctx, "jdbc/chidb"); } static void bind (Context ctx, String ln) throws NamingException, SQLException { // 创建一个DataSource实例 DataSource ods = new DataSource(); ods.setDriverType("thin"); ods.setServerName("Chicago"); ods.setNetworkProtocol("tcp"); ods.setDatabaseName("chidb"); ods.setPortNumber(1521); ods.setUser("guest"); ods.setPassword("guest"); // 把DataSource实例注册到JNDI中 System.out.println ("Doing a bind with the logical name : " + ln); ctx.bind (ln,ods); System.out.println ("SUCcessfully bound"); } static void lookup (Context ctx, String ln) throws NamingException, SQLException { // 从JNDI中查询DataSource实例 System.out.println ("Doing a lookup with the logical name : " + ln); DataSource ods = (DataSource) ctx.lookup (ln); System.out.println ("Successful lookup"); // 从查询到的DataSource实例中获取数据库连接 Connection conn = ods.getConnection(); // 进行数据库操作 getUserName(conn); // 关闭连接 conn.close(); conn = null; } static void getUserName(Connection conn) throws SQLException { // 生成一个Statement实例 Statement stmt = conn.createStatement (); // 从addressbook表中选中姓名列 ResultSet rset = stmt.executeQuery ("select NAME from addressbook"); // 列出addressbook表所有人的姓名 while (rset.next ()) System.out.println ("Name is " + rset.getString (1)); // 关闭RseultSet实例 rset.close(); rset = null; // 关闭Statement实例 stmt.close(); stmt = null; stmt = null; } } 程序首先生成了一个Context实例。javax.naming.Context接口定义了名称服务环境(N aming Context)及该环境支持的操作。名称服务环境实际上是由名称和对象间的相互映 射组成。程序中初始化名称服务环境的环境工厂(Context Factory)是com.sun.jndi. fscontext.RefFSContextFactory(该类在fscontext.jar中可以找到,由于fscontext. jar中包含的不是标准的API,用户需要从www.javasoft.com中的JNDI专区下载一个名为 fscontext1_2beta3.zip的压缩文件,在该文件中可以找到fscontext.jar)。环境工厂的 作用是生成名称服务环境的实例,javax.naming.spi.InitialContextFactory接口定义 了环境工厂应该如何初始化名称服务环境。在初始化名称服务环境时还需要定义环境的 URL。程序中使用的是"file:JNDI",也就是把环境保存在本地硬盘的JNDI目录下。 初始化了名称服务环境后,就可以把数据源实例注册到名称服务环境中。注册时调用javax.naming.Context.bind()方法,参数为注册名称和注册对象。注册成功后,在JNDI目 录下会生成一个.binding文件,该文件记录了当前名
|