分享
 
 
 

PostgreSQL数据库学习手册之JDBC接口

王朝mssql·作者佚名  2008-05-18
窄屏简体版  字體: |||超大  

Chapter 5. JDBC 接口

Table of Contents

5.1. 设置 JDBC 驱动

5.1.1. 获取驱动

5.1.2. 设置类路径

5.1.3. 为 JDBC准备数据库

5.2. 使用驱动

5.2.1. 装入 JDBC

5.2.2. 装载驱动

5.2.3. 与数据库联接

5.2.4. 关闭联接

5.3. 发出查询和处理结果

5.3.1. 使用 Statement或 PreparedStatement 接口

5.3.2. 使用ResultSet(结果集)接口

5.4. 执行更新

5.5. 创建和更改数据库对象

5.6. 存储二进制数据

5.7. PostgreSQL 对 JDBC API的扩展

5.7.1. 访问这些扩展

5.7.2. 几何数据类型

5.7.3. 大对象

5.8. 在一个多 Threaded (线程) 或 Servlet (服务器小应用)环境里使用驱动

5.9. 连接池和 DataSources

5.9.1. JDBC,JDK 版本支持

5.9.2. JDBC 连接池 API

5.9.3. 应用服务器:ConnectionPoolDataSource

5.9.4. 应用:DataSource

5.9.5. DataSources 和 JNDI

5.9.6. 特定的应用服务器配置

5.10. 深入阅读

作者: 最初由 Peter T. Mount (<peter@retep.org.uk>)执笔,他是 JDBC 驱动最初的作者.

JDBC 是 Java 1.1 及以后的核心 API. 它为 SQL 兼容的数据库提供了一个标准的接口集合.

PostgreSQL 提供了 类型 4 JDBC 驱动. 类型 4 表明该驱动是用纯 Java 书写的,并且与数据库之间使用数据库自己的网 络协议通讯.因此,驱动是平台无关的.一旦编译,该驱动可以用于任意平台.

本章并不想作为完整的 JDBC 编程的指导,但应该能帮你走出第一步. 更多信息请参考标准 JDBC API 文档. 同样,读一下包含在源代码里的例子.其中的基本例子在这里使用.

5.1. 设置 JDBC 驱动

5.1.1. 获取驱动

预编译好的驱动通常可以在 PostgreSQL JDBC 站点 找到.

另外你可以直接从源程序中制作驱动.尽管你只有在自己改动了驱动的代码 情况下才需要这么做。 相关的细节请参考PostgreSQL安装指导。在安装完成后,驱动应该在 PREFIX/share/java/postgresql.jar。 生成的驱动应该是为你运行的 Java 版本制作的。如果你用 1.1 JDK 制作, 那么你制作了一愕支持 JDBC 1 规范的驱动,如果你用 Java 2 JDK(比如, JDK 1.2 或者 JDK 1.3),你将制作一个支持 JDBC 2 规范的版本。

5.1.2. 设置类路径

要使用驱动,它的 JAR 归档 (如果你从源程序制作,那么名字叫 postgresql.jar,否则它很可能叫 jdbc7.2-1.1.jar 或 jdbc7.2-1.2.jar -- 分别用于 jdbc1 和 jdbc2) 必须包含在类路径里,你要么是把路径放到 CLASSPATH 环境变量里,要么是使用 java 命令行上的标记.

比如,我有一个使用 JDBC 驱动的应用,该应用访问一个存有天文对象的大数据库. 我的应用已经写好了,并且 JDBC 驱动 安装在 /usr/local/lib 目录,而 Java JDK 安装在 /usr/local/jdk1.3.1.要运行应用, 我可以用∶

export CLASSPATH=/usr/local/lib/finder.jar(1):/usr/local/pgsql/share/java/postgresql.jar:.

java uk.org.retep.finder.Main

(1)

finder.jar 里面包含 Finder 应用.

在应用里装载驱动的内容在 Section 5.2 里介绍.

5.1.3. 为 JDBC准备数据库

因为 Java 只使用 TCP/IP 联接, 所以 PostgreSQL服务器 必须配置成接受 TCP/IP 联接,我们可以通过在 postgresql.conf 文件里设置 tcpip_socket = true 或者启动 postmaster 的时候 带-i参数实现这个目地.

同样,在 pg_hba.conf 文件里的 客户端认证设置也要配置好. 请参考管理员手册获取细节. JDBC 驱动支持 trust,ident,password, md5 和 crypt 认证方式.

5.2. 使用驱动

5.2.1. 装入 JDBC

任何使用 JDBC 的源程序 都需要输入 java.sql 包,用:

import java.sql.*;

Important: 不要输入 postgresql 包.如果这样做,你的源码将不能编译, 因为 javac 会被你搞糊涂。

5.2.2. 装载驱动

在你试图与数据库连接之前,你需要装载驱动. 有两种方法,那种更好取决于你使用的代码.

在第一种方法里,你的代码用 Class.forName() 方法显式装载驱动.对于 PostgreSQL,你要用:

Class.forName("org.postgresql.Driver");

这样将装载驱动,并且在装载时,驱动将自动与 JDBC 注册自己.

注意: forName() 方法可能抛出一个 ClassNotFoundException ,所以如果驱动不可获得时你需要捕获它.

这是最常用的方法,但是把你的代码限制于 PostgreSQL 专用. 如果你的代码以后还要访问其他数据库,并且你不想使用 任何 PostgreSQL 相关的扩展, 那么还有第二种方法可用.

第二种方法把驱动做为参数在 JVM启动时传递给它,使用 -D参数.比如:

java -Djdbc.drivers=org.postgresql.Driver example.ImageViewer

在这个例子里, JVM将试图把驱动作为它的初始化的一部分装载. 一旦完成,启动ImageViewer。

现在这个方法更好一点,因为它允许你的代码用于其他数据库, 而不用重新编译代码.唯一要修改的东西是 URL,我们下面要提到.

最后一件事情.当你的代码试图打开一个Connection, 而你收到一个抛出的 No driver available SQLException 例外,这可能是因为驱动不在 class path (类路径)里,或者参数值不正确.

5.2.3. 与数据库联接

在 JDBC 里,数据库是用URL (Uniform Resource Locator)(统一资源定位器)表示的. 在 PostgreSQL里, 这可以由下面几种格式之一表示:

*

jdbc:postgresql:database

*

jdbc:postgresql://host/database

*

jdbc:postgresql://host:port/database

这里:

host

服务器的主机名.缺省是 "localhost".

port

服务器监听的端口号. 缺省时是PostgreSQL标准的端口号(5432).

database

数据库名.

要联接(数据库),你需要从 JDBC获取一个 Connection 实例. 要做这些,你要使用 DriverManager.getConnection()方法:

Connection db = DriverManager.getConnection(url, username, password);

5.2.4. 关闭联接

要关闭数据库联接,只需要对 Connection 调用 close()方法:

db.close();

5.3. 发出查询和处理结果

在任何你想向数据库运行一个SQL语句的时候, 你都需要一个Statement 或 PreparedStatement 实例. 一旦你拥有了一个Statement 或 PreparedStatement,你就可以 发出一个查询. 这样将返回一个ResultSet 实例, 在其内部包含整个结果. Example 5-1 演示了这个过程.

Example 5-1. 在 JDBC 里处理一个简单的查询

这个例子将发出一个简单的查询然后用一个 Statement打印出每行的第一个字段.

Statement st = db.createStatement();

ResultSet rs = st.executeQuery("SELECT * FROM mytable where columnfoo = 500");

while(rs.next()) {

System.out.print("Column 1 returned ");

System.out.println(rs.getString(1));

}

rs.close();

st.close();

这个例子将使用 PreparedStatement 发出和前面一样的查询,并且在查询中制作数值.

int foovalue = 500;

PreparedStatement st = db.prepareStatement("SELECT * FROM mytable where columnfoo = ?");

st.setInt(1, foovalue);

ResultSet rs = st.executeQuery();

while(rs.next()) {

System.out.print("Column 1 returned ");

System.out.println(rs.getString(1));

}

rs.close();

st.close();

5.3.1. 使用 Statement或 PreparedStatement 接口

在使用Statement或 PreparedStatement接口时必须考虑下面的问题:

*

你可以将一个Statement或 PreparedStatement实例使用任意次. 你可以在打开一个联接后马上创建一个Statement 实例, 并且在联接的生存期里使用之. 你必须记住每个Statement或 PreparedStatement只能存在一个 ResultSet.

*

如果你需要在处理一个ResultSet的时候执行一个查询, 你只需要创建并且使用另外一个Statement.

*

如果你使用了 threads (线程),并且有几个使用数据库, 你对每个线程必须使用一个独立的Statement. 如果考虑使用线程, 请参考本文档稍后的 Section 5.8 章节, 因为这些内容包含一些重要的信息.

*

在你用完 Statement 或者 PreparedStatement 之后,你应该关闭它.

5.3.2. 使用ResultSet(结果集)接口

使用ResultSet接口时必须考虑下面的问题:

*

在读取任何数值的时候,你必须调用next(). 如果还有结果则返回真(true),但更重要的是,它为处理准备了数据行.

*

在 JDBC 规范里,你对一个字段应该只访问一次. 遵循这个规则是最安全的,不过目前 PostgreSQL 驱动将允许你对一个字段访问任意次.

*

一旦你结束对一个 ResultSet 的处理,你必须对之调用 close()来关闭它。

*

一旦你使用那个创建ResultSet的 Statement做另一个查询请求, 当前打开的 ResultSet 实例将自动关闭.

*

目前的 ResultSet 是只读的. 你不能通过 ResultSet 来更新数据. 如果你想更新数据,那么你就需要使用老式的风格来做它∶ 通过发出一条 SQL 更新语句.这么做是和 JDBC 规范兼容的,它并不要求驱动提供这个功能.

5.4. 执行更新

要改变数据(执行一个插入,更新或者删除操作),你要使用 executeUpdate() 方法. executeUpdate() 类似用于发出 select 的 executeQuery(),不过,它不返回 ResultSet,它返回的是插入,更新或者删除语句 影响的记录数.

Example 5-2. 简单的删除例子

这个例子将发出一个简单的删除并打印出删除的行数.

int foovalue = 500;

PreparedStatement st = db.prepareStatement("DELETE FROM mytable where columnfoo = ?");

st.setInt(1, foovalue);

int rowsDeleted = st.executeUpdate();

System.out.println(rowsDeleted + " rows deleted");

st.close();

5.5. 创建和更改数据库对象

要创建,更改或者删除一个类似表或者视图这样的数据库对象, 你要使用 execute() 方法. execute 类似于用于发出 select 的 executeQuery(),不过它不返回结果.

Example 5-3. 删除表的例子

这个例子删除一个表.

Statement st = db.createStatement();

ResultSet rs = st.executeQuery("DROP TABLE mytable");

st.close();

5.6. 存储二进制数据

PostgreSQL 提供两种不同的方法存储二进制数据. 二进制数据可以使用PostgreSQL的二进制数据类型 bytea存储在表中,或者使用大对象 特性,该特性以一种特殊的格式将二进制数据存储在一个独立的表中, 然后通过在你的表中保存一个指向该表的类型为 OID 的数值 来引用它.

为了判断那种方法比较合适,你必须理解每种方法的局限. bytea 数据类型并不适合存储非常大数量的二进制数据. 虽然类型为 bytea 的字段可以存储最多 1G 字节的二进制数据, 但是这样它会要求数量巨大的内存(RAM)来处理这样巨大 的数值.存储二进制的大对象的方法更适合存储非常大的数值, 但也有自己的局限.特别是删除一个包含大对象的行并未删除大对象. 删除大对象是一个需要处理的独立的操作.大对象还有一些安全性的问题, 因为人和联接到数据库的人都可以查看或者更改大对象,即使他们 没有查看/更新包含大对象的行的权限也一样.

7.2 是第一个支持 bytea 类型的 JDBC 驱动版本.在 7.2 中引入的这个功能同时也引入了一个和以往的版本不同的 行为.在 7.2 里,方法 getBytes(), setBytes(), getBinaryStream() 和 setBinaryStream() 操作 bytea 类型. 在 7.1 里这些方法操作和 OID 类型关联的大对象. 我们可以通过在 Connection 上设置 compatible 为数值 7.1 来获取旧的 7.1 的行为.

要使用 bytea 数据类型你只需要使用 getBytes(),setBytes(), getBinaryStream(),或者 setBinaryStream() 方法.

要使用大对象的功能,你可以使用 PostgreSQL JDBC 驱动提供的 LargeObject API,或者使用 getBLOB() 和 setBLOB() 方法.

Important: 对于 PostgreSQL 而言,你必须在 一次 SQL 事务内访问大对象.你应该使用 带 false 输入参数的 setAutoCommit() 方法打开一个事务.

注意: 在将来的 JDBC 驱动中, getBLOB() 和 setBLOB() 方法可能不再操作大对象,而是将处理 bytea 数据类型. 因此如果你要用大对象,我们建议你使用 LargeObject API.

Example 5-4. 二进制数据例子

比如,假设你有一个表包含一幅图像和它的文件名, 并且你还想在 bytea 字段里存储图像∶

CREATE TABLE images (imgname text, img bytea);

要插入一幅图象,你可以:

File file = new File("myimage.gif");

FileInputStream fis = new FileInputStream(file);

PreparedStatement ps = conn.prepareStatement("INSERT INTO images VALUES (?, ?)");

ps.setString(1, file.getName());

ps.setBinaryStream(2, fis, file.length());

ps.executeUpdate();

ps.close();

fis.close();

这里,setBinaryStream() 把来自一个流的 一些数目的字节转换成类型 bytea 的字段. 如果图像的内容已经放在 byte[] 里面了, 那么你也可以用 setBytes() 方法干这件事.

检索一幅图象甚至更容易(我在这里使用PreparedStatement,当然用Statement也是一样的):

PreparedStatement ps = con.prepareStatement("SELECT img FROM images WHERE imgname=?");

ps.setString(1, "myimage.gif");

ResultSet rs = ps.executeQuery();

if (rs != null) {

while(rs.next()) {

byte[] imgBytes = rs.getBytes(1);

// use the stream in some way here

}

rs.close();

}

ps.close();

这里的二进制数据是以 byte[] 形式检索的.你也可以使用一个 InputStream.

另外你可能会需要存储一个非常大的文件,因此希望使用 LargeObject API 存储该文件∶

CREATE TABLE imagesLO (imgname text, imgOID OID);

要插入一个图像,你可以用∶

// 所有大对象 API 调用都必须在一次事务中

conn.setAutoCommit(false);

// 获取大对象管理器以便进行操作

LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();

//创建一个新的大对象

int oid = lobj.create(LargeObjectManager.READ | LargeObjectManager.WRITE);

//打开一个大对象进行写

LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE);

// 现在打开文件

File file = new File("myimage.gif");

FileInputStream fis = new FileInputStream(file);

// 从文件拷贝数据到大对象

byte buf[] = new byte[2048];

int s, tl = 0;

while ((s = fis.read(buf, 0, 2048)) > 0)

{

obj.write(buf, 0, s);

tl += s;

}

// 关闭大对象

obj.close();

//现在向 imgesLO 插入行

PreparedStatement ps = conn.prepareStatement("INSERT INTO imagesLO VALUES (?,?)");

ps.setString(1, file.getName());

ps.setInt(2, oid);

ps.executeUpdate();

ps.close();

fis.close();

从大对象中检索图像∶

// 所有 LargeObject API 调用都必须在一个事务里

conn.setAutoCommit(false);

// 获取大对象管理器以便进行操作

LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();

PreparedStatement ps = con.prepareStatement("SELECT imgOID FROM imagesLO WHERE imgname=?");

ps.setString(1, "myimage.gif");

ResultSet rs = ps.executeQuery();

if (rs != null) {

while(rs.next()) {

//打开大对象读

int oid = rs.getInt(1);

LargeObject obj = lobj.open(oid, LargeObjectManager.READ);

//读取数据

byte buf[] = new byte[obj.size()];

obj.read(buf, 0, obj.size());

//在这里对读取的数据做些处理

// 关闭对象

obj.close();

}

rs.close();

}

ps.close();

5.7. PostgreSQL 对 JDBC API的扩展

PostgreSQL 是一种可扩展的数据库系统. 你可以向数据库后端里增加你自己的函数,这些函数可以供查询调用, 甚至你可以增加你自己的数据类型.因为这些是 PostgreSQL 特有的功能,因此我们在 Java 里面支持它们,同时还带着一套扩展的 API.在标准驱动的核心里实际上使用了这些扩展 来实现大对象等等.

5.7.1. 访问这些扩展

要获得某些扩展,你需要使用 org.postgresql.PGConnection 类里的一些额外的方法,这时,你需要转换 Driver.getConnection() 的返回值.比如∶

Connection db = Driver.getConnection(url, username, password);

// ...

// 稍后

Fastpath fp = ((org.postgresql.PGConnection)db).getFastpathAPI();

5.7.1.1. 类 org.postgresql.PGConnection

public class PGConnection

这些是用于获取 PostgreSQL 的扩展 的额外的方法.

5.7.1.1.1. 方法

*

public Fastpath getFastpathAPI() throws SQLException

这个方法为当前联接返回 Fastpath API. 主要用于大对象API.

使用这个方法的最好方式是∶

import org.postgresql.fastpath.*;

...

Fastpath fp = ((org.postgresql.PGConnection)myconn).getFastpathAPI();

这里的myconn是一个已经打开的与 PostgreSQL 的Connection.

返回∶. 一个可以用来访问 PostgreSQL 后端里面的函数的 Fastpath 对象.

抛出∶. 在第一次初始化的时候 Fastpath 抛出的SQLException。

*

public LargeObjectManager getLargeObjectAPI() throws SQLException

这个方法为当前联接返回一个大对象 API.

使用这个方法的最佳手段如下∶

import org.postgresql.largeobject.*;

...

LargeObjectManager lo = ((org.postgresql.PGConnection)myconn).getLargeObjectAPI();

这里的myconn是一个已经打开的与 PostgreSQL 的Connection.

返回∶. 实现大对象 API 的LargeObject对象.

抛出∶. 在第一次初始化的时候LargeObject抛出的 SQLException.

*

public void addDataType(String type, String name)

这个方法允许客户端代码为PostgreSQL中比较独特的数据类型 加一个句柄.通常,驱动器不认识的数据类型是由 ResultSet.getObject() 以一个PGobject实例的形式返回的. 这个方法允许你写一个扩展PGobject 的类,然后告诉驱动该类型名子,以及要使用的类名子. 这个方法的缺点是,每次你建立新联接的时候,你都要调用这个方法.

使用这个用法的最佳手段是:

...

((org.postgresql.PGConnection)myconn).addDataType("mytype","my.class.name");

...

这里的myconn是一个已经打开的与 PostgreSQL 的Connection.做控制的类必须扩展 org.postgresql.util.PGobject.

5.7.1.2. 类 org.postgresql.Fastpath

public class Fastpath extends Object

java.lang.Object

|

+----org.postgresql.fastpath.Fastpath

Fastpath是一套存在于libpqC 接口里的 API , 并且这个接口允许客户机器执行后端数据库的函数. 大多数客户端代码不需要使用这个方法,但是我们还是提供这个方法, 因为大对象 API 使用它.

要使用这个扩展,你需要输入 postgresql.fastpath包,使用下面行:

import org.postgresql.fastpath.*;

然后,在你的代码里,你需要获取一个FastPath对象:

Fastpath fp = ((org.postgresql.PGConnection)conn).getFastpathAPI();

这样将返回一个实例,该实例与你发出命令的数据库联接相关联. 必须把Connection转换成 org.postgresql.PGConnection, 因为getFastpathAPI()是我们自己的方法之一,而不是 JDBC的. 一旦你拥有了 Fastpath 实例, 你就可以使用 fastpath() 方法执行一个后端函数.

又见∶. FastpathFastpathArg, LargeObject

5.7.1.2.1. 方法

*

public Object fastpath(int fnid,

boolean resulttype,

FastpathArg args[]) throws SQLException

向PostgreSQL后端发送一个函数调用.

参数∶. fnid - 函数 id resulttype - 如果结果为整数则为真,如果为其它则为假 args - 传递给 fastpath 的 FastpathArguments

返回∶. 如果没有数据返回空(null), 如果结果为整数返回一个Integer, 否则返回 byte[]

*

public Object fastpath(String name,

boolean resulttype,

FastpathArg args[]) throws SQLException

通过名字向PostgreSQL后端发送一个函数调用.

注意: 函数名到函数 id 的映射必须存在, 通常先调用 addfunction(). 这是调用函数的优选方法,因为函数 id 在不同版本的后端里是会/可能改变的. 这个方法工作的例子,可以参阅 org.postgresql.LargeObject.

参数∶. name - 函数名称 resulttype - 如果结果是整数返回真 (true), 其他结果返回假 (false) args - 传递给 fastpath 的参数FastpathArguments

返回∶. 如果没有数据返回空 (null), 如果结果为整数返回一个 Integer, 否则返回 byte[]

又见∶. LargeObject

*

public int getInteger(String name,

FastpathArg args[]) throws SQLException

这个便利方法假设返回值是一个 Integer (整数)

参数∶. name - 函数名 args - 函数参数

返回∶. 整数结果

抛出∶. 如果发生了数据库访问错误或者没有结果抛出 SQLException.

*

public byte[] getData(String name,

FastpathArg args[]) throws SQLException

这个便利方法假设返回值是二进制数据

参数∶. name - 函数名 args - 函数参数

返回∶. 包含结果的 byte[] 数组

抛出∶. 如果发生了数据库访问错误或者没有结果抛出SQLException?

*

public void addFunction(String name,

int fnid)

这个方法向我们的(函数)检索表里增加一个函数. 用户代码应该使用addFunctions方法, 因为这个方法基于一个查询, 而不是 OID 硬代码.我们不保证一个函数的 OID 是静态的, 甚至运行在不同服务器的同版本的数据库也不能保证是静态的.

*

public void addFunctions(ResultSet rs) throws SQLException

这个方法接收一个包含两个字段的ResultSet. 字段 1 包含函数名, 字段 2 是 OID. 它读取整个ResultSet,把值装载入函数表.

Important: 调用完这个方法后记得用close()关闭 ResultSet!!

关于函数名查找实现的信息: PostgreSQL 在pg_proc表里存储函数 id 和它们对应的名称, 在查找时不是从该表里查询每个所需函数的名称, 而是使用了一个Hashtable (散列表). 同样,只有需要的函数的名称才放到这个表里,以保证连接速度尽可能快.

org.postgresql.LargeObject 类在启动时执行一个查询, 并且把返回的 ResultSet 传递给这里提到的 addFunctions()方法. 一旦这些工作完成,LargeObjectAPI就用名称引用函数.

不要以为手工把它们转换成 OID 就可以了. 的确,目前这样做是可以用的,但随着开发的进行这些可能被修改 (在 V7.0 版本的讨论中有一些关于这些的话题), 所以这样做是防止未来可能出现的任何不受保障的痛苦的手段.

又见∶. LargeObjectManager

*

public int getID(String name) throws SQLException

这个方法返回与函数名关联的函数 id, 如果还没有对这个函数名调用 addFunction()或 addFunctions(), 那么抛出一个SQLException.

5.7.1.3. 类 org.postgresql.fastpath.FastpathArg

public class FastpathArg extends Object

java.lang.Object

|

+----org.postgresql.fastpath.FastpathArg

每个 fastpath 调用都需要一个参数列表,其数目和类型取决于被调用的函数. 这个类实现了提供这个功能所需要的方法.

关于如何使用这个方法的例子, 参阅 org.postgresql.LargeObject 包

又见∶. Fastpath, LargeObjectManager, LargeObject

5.7.1.3.1. 构造器

*

public FastpathArg(int value)

构造一个包含一个整数值的参数

参数∶. value - 待设置的 int (整数)值

*

public FastpathArg(byte bytes[])

构造一个包含一个字节数组的参数

参数∶. bytes - 要保存的数组

*

public FastpathArg(byte buf[],

int off,

int len)

构造一个包含一个数组的一部分的参数

参数∶.

buf

源数组

off

数组内的偏移量

len

要包括的数据的长度

*

public FastpathArg(String s)

构造一个字符串组成的参数.

5.7.2. 几何数据类型

PostgreSQL 有一个往表里存储几何特性的数据类型集. 范围包括点,线,和多边形. 我们通过 org.postgresql.geometric 包在 Java 里支持这些类型. 它包括扩展了 org.postgresql.util.PGobject 类的类. 参考该类获取如何实现你自己的数据类型的控制器的细节.

Class org.postgresql.geometric.PGbox

java.lang.Object

|

+----org.postgresql.util.PGobject

|

+----org.postgresql.geometric.PGbox

public class PGbox extends PGobject implements Serializable,

Cloneable

这个类在PostgreSQL里表示盒子 (box) 数据类型.

变量

public PGpoint point[]

这些是盒子的两个对角点.

构造器

public PGbox(double x1,

double y1,

double x2,

double y2)

参数∶

x1 - 第一个 x 坐标

y1 - 第一个 y 坐标

x2 - 第二个 x 坐标

y2 - 第二个 y 坐标

public PGbox(PGpoint p1,

PGpoint p2)

参数∶

p1 - 第一个点

p2 - 第二个点

public PGbox(String s) throws SQLException

参数∶

s -PostgreSQL语法里的盒子定义

抛出∶ SQLException

如果定义非法

public PGbox()

必须的构造(方法)

方法

public void setValue(String value) throws SQLException

这个方法设置这个对象的值.它应该被重载,但是仍然被子类调用.

参数∶

value - 一个代表对象值的字符串

抛出∶ SQLException

如果此数值对这个类型而言是非法的

覆盖∶

类 PGobject 里的 setValue

public boolean equals(Object obj)

参数∶

obj - 要比较的对象

返回∶

如果两个盒子相等返回真 (true)

覆盖∶

类 PGobject 里的 equals

public Object clone()

必须覆盖这个方法以允许对象被克隆 (cloned)

覆盖∶

类 PGobject 里的 equals

public String getValue()

返回∶

PostgreSQL句法需要的 PGbox

覆盖∶

getValue in class PGobject

Class org.postgresql.geometric.PGcircle

java.lang.Object

|

+----org.postgresql.util.PGobject

|

+----org.postgresql.geometric.PGcircle

public class PGcircle extends PGobject implements Serializable,

Cloneable

这个类代表 PostgreSQL 的圆数据类型,由一个点和一个半径组成

变量

public PGpoint center

这是圆心

double radius

这是半径

构造器

public PGcircle(double x,

double y,

double r)

参数∶

x - 圆心坐标

y - 圆心坐标

r - 圆半径

public PGcircle(PGpoint c,

double r)

参数∶

c - 描述圆心的 PGpoint

r - 圆半径

public PGcircle(String s) throws SQLException

参数∶

s -PostgreSQL里语法定义的圆.

抛出∶ SQLException

如果转换失败

public PGcircle()

这个构造(方法)被驱动器使用.

方法

public void setValue(String s) throws SQLException

参数∶

s - 用PostgreSQL的语法定义的圆.

抛出∶ SQLException

如果转换失败

覆盖∶

类 PGobject 里的 setValue

public boolean equals(Object obj)

参数∶

obj - 要对比的对象

返回∶

如果两个圆相同返回真 (true)

覆盖∶

类 PGobject 里的 equals

public Object clone()

必须重载这个方法以便允许对象被克隆 (cloned)

覆盖∶

类 PGobject 里的 clone

public String getValue()

返回∶

PostgreSQL 语法里的 PGcircle 字串

覆盖∶

PGobject 里的 getValue

Class org.postgresql.geometric.PGline

java.lang.Object

|

+----org.postgresql.util.PGobject

|

+----org.postgresql.geometric.PGline

public class PGline extends PGobject implements Serializable,

Cloneable

这个类实现由两个点组成的线.目前线还没有在后端实现,

但这个类保证在后端实现后即可使用(线).

变量

public PGpoint point[]

这是两个点.

构造器

public PGline(double x1,

double y1,

double x2,

double y2)

参数∶

x1 - 第一个点的x坐标

y1 - 第一个点的y坐标

x2 - 第二个点的x坐标

y2 - 第二个点的y坐标

public PGline(PGpoint p1,

PGpoint p2)

参数∶

p1 - 第一个点

p2 - 第二个点

public PGline(String s) throws SQLException

参数∶

s -PostgreSQL语法定义的点.

抛出∶ SQLException

当发生转换错误时

public PGline()

驱动需要

方法

public void setValue(String s) throws SQLException

参数∶

s -PostgreSQL里语法的线段的定义

抛出∶ SQLException

当发生转换错误时

覆盖∶

类 PGobject 里的 setValue

public boolean equals(Object obj)

参数∶

obj - 要比较的对象

返回∶

如果两条线段相同返回真 (true)

覆盖∶

类 PGobject 里的 equals

public Object clone()

这个方法必须被重载以便允许这个对象可以被克隆

覆盖∶

类 PGobject 里的 clone

public String getValue()

返回∶

PostgreSQL 语法里的 PGline

覆盖∶

类 PGobject 里的 getValue

Class org.postgresql.geometric.PGlseg

java.lang.Object

|

+----org.postgresql.util.PGobject

|

+----org.postgresql.geometric.PGlseg

public class PGlseg extends PGobject implements Serializable,

Cloneable

这样实现了一条包含两个点的 lseg (线段)

变量

public PGpoint point[]

这里是两个点

构造器

public PGlseg(double x1,

double y1,

double x2,

double y2)

参数∶

x1 - 第一个点的x坐标

y1 - 第一个点的y坐标

x2 - 第二个点的x坐标

y2 - 第二个点的y坐标

public PGlseg(PGpoint p1,

PGpoint p2)

参数∶

p1 - 第一个点

p2 - 第二个点

public PGlseg(String s) throws SQLException

参数∶

s -PostgreSQL里语法对线段定义的字串.

抛出∶ SQLException

在发生转换错误时

public PGlseg()

驱动要求

方法

public void setValue(String s) throws SQLException

参数∶

s -PostgreSQL里语法对线段定义的字串

抛出∶ SQLException

在发生转换错误时

覆盖∶

类 PGobject 里的 setValue

public boolean equals(Object obj)

参数∶

obj - 要比较的对象

返回∶

如果两条线段相等

覆盖∶

类 PGobject 里的 equals

public Object clone()

必须覆盖这个方法以便允许这个对象被克隆

覆盖∶

类 PGobject 里的 getValue

public String getValue()

返回∶

PostgreSQL 语法里的 PGlseg

覆盖∶

类 PGobject 里的 getValue

Class org.postgresql.geometric.PGpath

java.lang.Object

|

+----org.postgresql.util.PGobject

|

+----org.postgresql.geometric.PGpath

public class PGpath extends PGobject implements Serializable,

Cloneable

这是路径( 多线段图形, 可以为封闭的 )的实现

变量

public boolean open

如果路径开放时为真 (True),为封闭时为假

public PGpoint points[]

定义路径的点

构造器

public PGpath(PGpoint points[],

boolean open)

参数∶

points - 定义路径的 PGpoints

open - 如果路径是开放的为真 (True),封闭为假 (false)

public PGpath()

驱动需要

public PGpath(String s) throws SQLException

参数∶

s -PostgreSQL的语法定义的路径.

抛出∶ SQLException

在发生转换错误时

方法

public void setValue(String s) throws SQLException

参数∶

s -PostgreSQL的语法定义的路径的字串

抛出∶ SQLException

在发生转换失败时

覆盖∶

类 PGobject 里的 setValue

public boolean equals(Object obj)

参数∶

obj - 要比较的对象

返回∶

如果两个路径相同返回真 (true)

覆盖∶

类 PGobject 里的 equals

public Object clone()

必须覆盖这个方法以便允许这个对象被克隆

覆盖∶

clone in class PGobject

public String getValue()

这个方法返回PostgreSQL语法的多边形

覆盖∶

类 PGobject 里的 getValue

public boolean isOpen()

如果路径是开放的这个方法返回真 (true)

public boolean isClosed()

如果路径是封闭的这个方法返回真 (true)

public void closePath()

标记路径为封闭

public void openPath()

标记路径为开放

Class org.postgresql.geometric.PGpoint

java.lang.Object

|

+----org.postgresql.util.PGobject

|

+----org.postgresql.geometric.PGpoint

public class PGpoint extends PGobject implements Serializable,

Cloneable

这个类实现了 java.awt.Point 的一个版本,但用 double 表示参数.

它对应于 PostgreSQL 里的 point 数据类型.

变量

public double x

点的 X 坐标

public double y

点的 Y 坐标

构造器

public PGpoint(double x,

double y)

参数∶

x - 坐标

y - 坐标

public PGpoint(String value) throws SQLException

这个方法主要从其他几何类型调用 -- 当一个点嵌入它们的定义中时.

参数∶

value -PostgreSQL语法定义的点

public PGpoint()

驱动需要

方法

public void setValue(String s) throws SQLException

参数∶

s -PostgreSQL语法定义的点

抛出∶ SQLException

在转换失败时

覆盖∶

类 PGobject 里的 setValue

public boolean equals(Object obj)

参数∶

obj - 要比较的对象

返回∶

如果两个对象相同返回真 (true)

覆盖∶

类 PGobject 里的 equals

public Object clone()

必须覆盖这个方法以便允许这个对象被克隆

覆盖∶

类 PGobject 里的 clone

public String getValue()

返回∶

PostgreSQL里语法 PGpoint 的表示.

覆盖∶

类 PGobject 里的 getValue

public void translate(int x,

int y)

对点做指定数量的转换(位移).

参数∶

x - 向 x 轴增加的整型数量

y - 向 y 轴增加的整型数量

public void translate(double x,

double y)

对点做指定数量的转换(位移).

参数∶

x - 向 x 轴增加的双精度型数量

y - 向 y 轴增加的双精度型数量

public void move(int x,

int y)

把点移到指定坐标.

参数∶

x - 整数坐标

y - 整数坐标

public void move(double x,

double y)

把点移到指定坐标.

参数∶

x - 双精度坐标

y - 双精度坐标

public void setLocation(int x,

int y)

把点移到指定坐标. 参考

java.awt.Point 获取这个方法的描述信息

参数∶

x - 整数坐标

y - 整数坐标

又见∶

Point

public void setLocation(Point p)

把点移到指定坐标. 参考

java.awt.Point 获取这个方法的描述信息

参数∶

p - 移动的目的点 (Point)

又见∶

Point

Class org.postgresql.geometric.PGpolygon

java.lang.Object

|

+----org.postgresql.util.PGobject

|

+----org.postgresql.geometric.PGpolygon

public class PGpolygon extends PGobject implements Serializable,

Cloneable

这个类在PostgreSQL里实现了 polygon (多边形)数据类型.

变量

public PGpoint points[]

定义 polygon (多边形)的点

构造器

public PGpolygon(PGpoint points[])

使用一个 PGpoints 数组创建一个多边形

参数∶

points - 定义多边形 polygon 的点

public PGpolygon(String s) throws SQLException

参数∶

s - 用PostgreSQL语法定义的多边形.

抛出∶ SQLException

在转换失败时

public PGpolygon()

驱动需要

方法

public void setValue(String s) throws SQLException

参数∶

s - 用PostgreSQL语法定义的多边形.

抛出∶ SQLException

在转换失败时

覆盖∶

类 PGobject 里的 setValue

public boolean equals(Object obj)

参数∶

obj - 要比较的对象

返回∶

如果两个对象相同返回真 (true)

覆盖∶

类 PGobject 里的 equals

public Object clone()

必须覆盖这个方法以便允许这个对象被克隆

覆盖∶

类 PGobject 里的 clone

public String getValue()

返回∶

PostgreSQL里语法表示的 PGpolygon.

覆盖∶

类 PGobject 里的 getValue

5.7.3. 大对象

标准的 JDBC 规范里也支持大对象. 但是,那个接口有一些限制, 而PostgreSQL提供的 API 允许对对象内容的随机访问, 就象那是一个本地文件一样.

org.postgresql.largeobject 包为 Java 提供了libpqC 接口的大对象 API.它包含两个类, LargeObjectManager, 处理创建,打开和删除大对象的任务;以及 LargeObject,处理独立的对象.

5.7.3.1. 类org.postgresql.largeobject.LargeObject

public class LargeObject extends Object

java.lang.Object

|

+----org.postgresql.largeobject.LargeObject

这个类实现PostgreSQL的大对象接口.

它提供运行接口的基本的方法,另外还有一对方法为此对象提供 InputStream 和 OutputStream类.

通常,客户端代码将使用在 BLOB 里的方法 访问大对象.

但是,有时候需要低层次的大对象访问方法,那是 JDBC 规范还不支持的.

参考 org.postgresql.largeobject.LargeObjectManager 获取如何访问大对象和如何创建大对象的信息.

又见∶. LargeObjectManager

5.7.3.1.1. 变量

public static final int SEEK_SET

标识从一个文件的开头进行一次搜索

public static final int SEEK_CUR

标识从当前位置进行一次搜索

public static final int SEEK_END

标识从一个文件的结尾进行一次搜索

5.7.3.1.2. 方法

*

public int getOID()

返回这个 LargeObject 的 OID.

*

public void close() throws SQLException

这个方法关闭对象,在调用这个方法后你不能调用这个对象里的任何方法.

*

public byte[] read(int len) throws SQLException

从对象读取一些数据, 并且做为 byte[] 数组返回

*

public int read(byte buf[],

int off,

int len) throws SQLException

从对象读取一些数据到现有数组

参数∶.

buf

目的数组

off

数组内偏移量

len

读取的字节数

*

public void write(byte buf[]) throws SQLException

向对象里写入一个数组

*

public void write(byte buf[],

int off,

int len) throws SQLException

从数组里写一些数据到对象

参数∶.

buf

目标数组

off

数组内偏移量

len

写入字节数

5.7.3.2. 类org.postgresql.largeobject.LargeObjectManager

public class LargeObjectManager extends Object

java.lang.Object

|

+----org.postgresql.largeobject.LargeObjectManager

这个类型实现了PostgreSQL的大对象接口. 它提供了允许客户代码从数据库里创建,打开和删除大对象的方法. 在打开一个对象时,返回一个 postgresql.largeobject.LargeObject的实例, 然后它的方法就可以访问该对象.

这个类只能由 org.postgresql.PGConnection 创建 要访问这个类,使用下面的代码片段:

import org.postgresql.largeobject.*;

Connection conn;

LargeObjectManager lobj;

// ... 打开一个连接的代码 ...

lobj = ((org.postgresql.PGConnection)myconn).getLargeObjectAPI();

通常, 客户代码要使用 BLOB 方法访问大对象. 但是,有时候需要低层次的大对象访问方法,那是 JDBC 规范还不支持的.

请参考 org.postgresql.largeobject.LargeObject 获取如何控制大对象内容的信息.

5.7.3.2.1. 变量

public static final int WRITE

这个模式表明我们要写入大对象

public static final int READ

这个模式表明我们要读取大对象

public static final int READWRITE

这个模式是缺省的,表明我们要对大对象进行读和写的操作

5.7.3.2.2. 方法

*

public LargeObject open(int oid) throws SQLException

这个方法打开一个现有的大对象, 以其 OID 为基础. 这个方法假设 我们需要READ和WRITE访问模式 (缺省模式).

*

public LargeObject open(int oid,

int mode) throws SQLException

这个方法以其 OID 为基础打开一个现有的大对象. 并且允许设置访问模式.

*

public int create() throws SQLException

这个方法创建一个大对象, 返回它的 OID. 它把新创建的大对象模式设为缺省的READWRITE.

*

public int create(int mode) throws SQLException

这个方法创建一个大对象,返回它的 OID.并设置访问模式.

*

public void delete(int oid) throws SQLException

这个方法删除一个大对象.

*

public void unlink(int oid) throws SQLException

这个方法删除一个大对象.这个方法等同于 delete 方法, 并且作为类似使用"unlink"的 C API 出现.

5.8. 在一个多 Threaded (线程) 或 Servlet (服务器小应用)环境里使用驱动

许多 JDBC 驱动的一个共同问题是它们在任意时刻一个线程只能使用一个联接 Connection) - 否则可能一个在发送一个查询而另一个线程正在接受结果, 这个现象对数据库引擎是一个很糟糕的事情.

PostgreSQL JDBC 驱动都是线程安全的. 所以,如果你的应用要使用多线程, 那么你不必考虑任意时刻只允许一个线程使用数据库的复杂算法.

如果一个线程在其他线程正在使用数据库时试图访问数据库, 那么它将等到另一个线程完成当前操作之后进行. 如果这是一个普通的 SQL 语句, 那么该操作就是发送该语句, 并检索任何 ResultSet (完整的). 如果这是一个 Fastpath 调用 (例如: 从一个 LargeObject里读取一个数据块), 那么这时就发送, 和接收该数据块.

这对客户端的大小应用都很好, 但是可能造成服务器端小应用 (servlets) 的性能问题. 对于 servlets, 你可能会有很沉重的联接负荷. 如果你有好几个线程执行查询, 那么它们每个都暂停可不是你想看到的.

要解决这个问题, 我们建议你创建一个联接池. (pool of Connections) 当一个线程需要使用数据库, 它向管理类请求一个 Connection. 管理器赋予该线程一个空闲联接, 然后把它标记为忙. 如果没有空闲联接, 管理器就打开一个. 一旦线程完成数据库使用, 该线程把联接返回给管理器, 管理器既可以关闭该联接, 也可以把它加到联接池里. 管理器同样还检查联接是否仍然激活, 如果联接死亡了就把它从联接池删除.

所以, 对于服务器端小应用 ( servlets ), 选择单联接还是联接池是你的责任. 使用联接池的优点是线程不会成为单个网络联接的瓶颈. 缺点是这样做增加了服务器端 的负荷, 因为对每个Connection都要创建一个后端进程. 选择何种方式是你和你的应用的需求决定的.

5.9. 连接池和 DataSources

5.9.1. JDBC,JDK 版本支持

JDBC 2 以一个附加的 API 的方式引入了标准连接池的特性,这个 附加的 API 叫做 JDBC 2.0 可选包(也称作 JDBC 2.0 标准扩展)。因此这些特性就被包含到核心的 JDBC 3 API 中了。 PostgreSQL JDBC 驱动和 JDK 1.3.x 一起支持这些特性,以及 JDBC 2.0 可选包,或者是和 JDK 1.4+ (JDBC 3)一起,也支持这个特性。大多数应用服务器包含 JDBC 2.0 可选包,但我们也可以从 SUN 单独获得这些东西: JDBC下载站。

5.9.2. JDBC 连接池 API

JDBC API 为连接池提供了一个客户端和 一个服务器端的接口。客户端接口是 javax.sql.DataSource, 通常就是应用代码用来请求一个缓冲了的数据库连接的东西。 服务器接口是 javax.sql.ConnectionPoolDataSource, 通常是大多数应用服务器和 PostgreSQL JDBC 驱动打交道的接口。

在应用服务器环境里,应用服务器配置通常将指向 PostgreSQL ConnectionPoolDataSource 实现, 而应用组件代码将通常要求一个由应用服务器实现的 DataSource(不是由 PostgreSQL)。

在一个没有应用服务器的环境里,PostgreSQL 提供了 两种应用可以直接使用的 DataSource 的实现。 一种实现执行连接池,另外一种只是简单的通过 DataSource 接口 提供访问数据库的连接,而不使用任何缓冲池。同样,这些实现不应该 在一个应用服务器环境里使用,除非应用服务器不支持 ConnectionPoolDataSource 接口。

5.9.3. 应用服务器:ConnectionPoolDataSource

PostgreSQL 包含了一个用于 JDBC 2 的 ConnectionPoolDataSource 的实现,以及一个用于 JDBC 3 的实现:

Table 5-1. ConnectionPoolDataSource 实现

JDBC实现类

2org.postgresql.jdbc2.optional.ConnectionPool

3org.postgresql.jdbc3.Jdbc3ConnectionPool

两种实现都使用了同样的配置模式。JDBC 要求一个 ConnectionPoolDataSource 通过 JavaBean 属性来实现, 因此每个这样的属性都存在获取和设置方法:

Table 5-2. ConnectionPoolDataSource 配置属性

属性类型描述

serverNameStringPostgreSQL 数据库服务器主机名

databaseNameStringPostgreSQL 数据库名

portNumberintPostgreSQL 数据库服务器监听的 TCP/IP 端口 (为 0 则使用缺省端口)

userString用来进行数据库连接的用户

passwordString用来进行数据库连接的口令

defaultAutoCommitboolean提交给调用者的时候连接是应该打开 autoCommit 还是应该关闭。 缺省是 false,关闭 autoCommit。

许多应用服务器使用属性风格的语法来配置这些属性, 因此把属性当作一块文本输入应该并不罕见。

Example 5-5. ConnectionPoolDataSource 配置例子

如果应用服务器提供了单一的区域用于输入所有属性, 那么它们通常会象下面这样列出:

serverName=localhost

databaseName=test

user=testuser

password=testpassword

或者是用分号,而不是换行来分隔,象这样:

serverName=localhost;databaseName=test;user=testuser;password=testpassword

5.9.4. 应用:DataSource

PostgreSQL 包含两个用于 JDBC 2 的 DataSource,以及两个用于 JDBC 3的。 连接池的实现在客户端调用 close 方法的时候 实际上并不关闭连接,而是把连接返回到一个可用连接的连接池中 给其它客户端使用。这样就避免了任何重复打开和关闭连接造成的 开销,并且允许大量的客户端分享相对较少的数据库连接。

这里提供的连接池 datasource 实现并非世上特性最丰富的。 比如,连接在池本身关闭之前绝对不会关闭;而且也没有办法缩小连接池。 同样,非缺省配置的用户的连接请求无法如池。许多应用服务器提供 更加高级的连接池特性,并且使用的是 ConnectionPoolDataSource 实现。

Table 5-3. DataSource 实现

JDBC连接池实现类

2否org.postgresql.jdbc2.optional.SimpleDataSource

2是org.postgresql.jdbc2.optional.PoolingDataSource

3否org.postgresql.jdbc3.Jdbc3SimpleDataSource

3是org.postgresql.jdbc3.Jdbc3PoolingDataSource

所有实现使用同样的配置模式。JDBC 要求 DataSource 通过 JavaBean 属性配置,因此每种这个 属性都有获取和设置属性。

Table 5-4. DataSource 配置属性

属性类型描述

serverNameStringPostgreSQL 数据库服务器主机名

databaseNameStringPostgreSQL 数据库名

portNumberintPostgreSQL 数据库服务器监听的 TCP/IP 端口 (或者 0 表示使用缺省端口)

userString用于连接数据库的用户

passwordString用于连接数据库的口令

连接池实现要求一些额外的配置属性:

Table 5-5. 额外的连接池 DataSource 配置属性

属性类型描述

dataSourceNameString每一个连接池 DataSource 必须有一个唯一的名字

initialConnectionsint连接池初始化的时候要创建的数据库连接数目

maxConnectionsint允许打开的最大数据库连接个数。如果请求了更多的连接, 那么调用者将挂起,直到有一个连接返回给连接池。

下面是一个使用连接池 DataSource 的典型应用的代码:

Example 5-6. DataSource 代码例子

初始化连接池 DataSource 的代码例子看起来会象这样:

Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource();

source.setDataSourceName("A Data Source");

source.setServerName("localhost");

source.setDatabaseName("test");

source.setUser("testuser");

source.setPassword("testpassword");

source.setMaxConnections(10);

然后使用来自连接池的代码看起来会象这样。 请注意关闭连接是非常关键的,否则这个池子就会“泄漏”连接, 最后把所有客户端都锁在外面。

Connection con = null;

try {

con = source.getConnection();

// use connection

} catch(SQLException e) {

// log error

} finally {

if(con != null) {

try {con.close();}catch(SQLException e) {}

}

}

5.9.5. DataSources 和 JNDI

所有 ConnectionPoolDataSource 和 DataSource 实现都可以存储在 JNDI 里。在非连接池的实现中, 每次从 JNDI 中检索对象都将创建一个新的实例, 带有和存储的实例同样的设置。对于连接池实现而言,同一个实例 是在可得的情况下检索出来的(也就是说,没有其它 JVM 从 JNDI 中检索连接池),否则就创建同样设置的新的实例。

在应用服务器环境,通常是应用服务器的 DataSource 实例将存储在 JNDI 中,而不是 PostgreSQL ConnectionPoolDataSource 的实现。

在应用服务器环境,应用可以在 JNDI 中存储 DataSource, 这样它就不用制作一个指向 DataSource 的引用提供给 所有可能需要的应用组件使用它:

Example 5-7. DataSource JNDI 代码例子

初始化连接池 DataSource 并且把它加到 JNDI 的代码 看起来可能象这样:

Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource();

source.setDataSourceName("A Data Source");

source.setServerName("localhost");

source.setDatabaseName("test");

source.setUser("testuser");

source.setPassword("testpassword");

source.setMaxConnections(10);

new InitialContext().rebind("DataSource", source);

Then code to use a connection from the pool might look like this:

Connection con = null;

try {

DataSource source = (DataSource)new InitialContext().lookup("DataSource");

con = source.getConnection();

// use connection

} catch(SQLException e) {

// log error

} catch(NamingException e) {

// DataSource wasn't found in JNDI

} finally {

if(con != null) {

try {con.close();}catch(SQLException e) {}

}

}

5.9.6. 特定的应用服务器配置

在这里包含特定的应用服务器的配置信息。

5.10. 深入阅读

如果你还没有读过,我建议你阅读一下 JDBC API 文档(和 Sun 的 JDK一并提供),和 JDBC 规范.两者都可以在 http://java.sun.com/products/jdbc/index.html 获得.

http://jdbc.postgresql.org 包含本文档没有包含的更新信息,同样还有编译好了的驱动.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有