8.7. PostgreSQL 对 JDBC API 的扩展 #
PostgreSQL 是一个可扩展的数据库系统。你可以向后端添加自己的函数,然后从查询中调用它们,甚至添加你自己的数据类型。由于这些是 PostgreSQL 独有的功能,我们用一组扩展 API 从 Java 中支持它们。标准驱动核心中的一些功能实际上就是用这些扩展来实现大对象等特性的。
8.7.1. 访问扩展
要访问其中一些扩展,你需要使用
org.postgresql.Connection
类中的一些额外方法。在这种情况下,你需要对
Driver.getConnection() 的返回值进行强制转换。例如:
Connection db = Driver.getConnection(url, username, password); // ... // later on Fastpath fp = ((org.postgresql.Connection)db).getFastpathAPI();
8.7.1.1. org.postgresql.Connection 类
public class PGConnection
这些是用于访问
PostgreSQL 扩展的额外方法。java.sql.Connection 中定义的方法不在此列出。
8.7.1.1.1. 方法
public Fastpath getFastpathAPI() throws SQLException
这将返回当前连接的 Fastpath API。它主要供大对象 API 使用。
使用它的最佳方式如下:
import org.postgresql.fastpath.*; ... Fastpath fp = ((org.postgresql.Connection)myconn).getFastpathAPI();
其中
myconn是一个到 PostgreSQL 的已打开的Connection。返回:. 一个允许访问 PostgreSQL 后端上函数的 Fastpath 对象。
抛出:. 首次初始化时由 Fastpath 抛出的 SQLException
public LargeObjectManager getLargeObjectAPI() throws SQLException
这将返回当前连接的大对象 API。
使用它的最佳方式如下:
import org.postgresql.largeobject.*; ... LargeObjectManager lo = ((org.postgresql.Connection)myconn).getLargeObjectAPI();
其中
myconn是一个到 PostgreSQL 的已打开的Connection。返回:. 一个实现了该 API 的
LargeObject对象抛出:. 首次初始化时由
LargeObject抛出的SQLExceptionpublic void addDataType(String type, String name)
这允许客户端代码为 PostgreSQL 较独特的数据类型之一添加一个处理器。通常,驱动不认识的数据类型会被
ResultSet.getObject()作为PGobject实例返回。这个方法允许你编写一个扩展PGobject的类,并告诉驱动要使用的类型名和类名。它的缺点是,每次建立连接时你都必须调用这个方法。使用它的最佳方式如下:
... ((org.postgresql.Connection)myconn).addDataType("mytype","my.class.name"); ...其中
myconn是一个到 PostgreSQL 的已打开的Connection。处理类必须扩展org.postgresql.util.PGobject。
8.7.1.2. org.postgresql.Fastpath 类
public class Fastpath extends Object java.lang.Object | +----org.postgresql.fastpath.Fastpath
Fastpath 是一个存在于
libpq C 接口中的 API,它允许一台客户端机器在数据库后端上执行一个函数。大多数客户端代码不需要使用这个方法,但之所以提供它,是因为大对象 API 用到它。
要使用它,你需要用下面这一行导入
org.postgresql.fastpath 包:
import org.postgresql.fastpath.*;
然后,在你的代码中,你需要获取一个
FastPath 对象:
Fastpath fp = ((org.postgresql.Connection)conn).getFastpathAPI();
这将返回一个与你可用它来发出命令的数据库连接相关联的实例。必须把
Connection 强制转换为
org.postgresql.Connection,因为
getFastpathAPI() 是一个扩展方法,不属于 JDBC。一旦你有了一个
Fastpath 实例,就可以使用
fastpath() 方法来执行一个后端函数。
参见:. FastpathFastpathArg、LargeObject
8.7.1.2.1. 方法
public Object fastpath(int fnid, boolean resulttype, FastpathArg args[]) throws SQLException向 PostgreSQL 后端发送一次函数调用。
参数:.
fnid- 函数 idresulttype- 如果结果是一个整数则为 true,对于其他结果为 falseargs- 要传递给 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,对于其他结果为 falseargs- 要传递给 fastpath 的FastpathArguments返回:. 无数据时为 null,整数结果时为 Integer,否则为 byte[]
参见:.
LargeObjectpublic int getInteger(String name, FastpathArg args[]) throws SQLException这个便捷方法假定返回值是一个 Integer
参数:.
name- 函数名args- 函数参数返回:. 整数结果
抛出:. 发生数据库访问错误或没有结果时的
SQLExceptionpublic byte[] getData(String name, FastpathArg args[]) throws SQLException这个便捷方法假定返回值是二进制数据。
参数:.
name- 函数名args- 函数参数返回:. 包含结果的 byte[] 数组
抛出:. 发生数据库访问错误或没有结果时的
SQLExceptionpublic void addFunction(String name, int fnid)这会向我们的查找表添加一个函数。用户代码应当使用基于查询的
addFunctions方法,而不是硬编码 oid。一个函数的 oid 不保证保持不变,即使在同一版本的不同服务器上也是如此。public void addFunctions(ResultSet rs) throws SQLException
这需要一个包含两列的
ResultSet。第 1 列包含函数名,第 2 列包含 oid。它会读取整个ResultSet,把这些值装入函数表。重要
记得在调用它之后对
ResultSet调用close()!关于函数名查找的实现说明
PostgreSQL 把函数 id 及其对应的名称存储在
pg_proc表中。为了在本地加快速度,不是在需要时从该表中逐个查询函数,而是使用一个Hashtable。而且,只有所需的函数才会被输入到这个表中,以使连接时间尽可能快。org.postgresql.LargeObject类在启动时执行一次查询,并把返回的ResultSet传递给这里的addFunctions()方法。完成之后,大对象 API 就可以按名称引用这些函数。不要以为手动把它们转换成 oid 就能工作。好吧,目前它们可以,但在开发过程中它们可能改变(V7.0 曾有过一些关于此的讨论),因此这样实现是为了避免将来出现不必要的麻烦。
参见:.
LargeObjectManagerpublic int getID(String name) throws SQLException
这将返回与名称相关联的函数 id。如果没有为这个名称调用过
addFunction()或addFunctions(),那么就会抛出SQLException。
8.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
8.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)
构造一个由一个 String 组成的参数。
8.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
如果值对该类型无效则抛出
Overrides:
setValue in class PGobject
public boolean equals(Object obj)
参数:
obj - 要比较的对象
返回值:
如果两个矩形相同则为 true
Overrides:
equals in class PGobject
public Object clone()
必须覆盖此方法才能克隆该对象
Overrides:
clone in class PGobject
public String getValue()
返回值:
按 PostgreSQL 所期望语法表示的 PGbox
Overrides:
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 的 circle 数据类型,由一个点和一个半径组成
变量
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
转换失败时
Overrides:
setValue in class PGobject
public boolean equals(Object obj)
参数:
obj - 要比较的对象
返回值:
如果两个圆相同则为 true
Overrides:
equals in class PGobject
public Object clone()
必须覆盖此方法才能克隆该对象
Overrides:
clone in class PGobject
public String getValue()
返回值:
按 PostgreSQL 所期望语法表示的 PGcircle
Overrides:
getValue in class PGobject
Class org.postgresql.geometric.PGline
java.lang.Object
|
+----org.postgresql.util.PGobject
|
+----org.postgresql.geometric.PGline
public class PGline extends PGobject implements Serializable,
Cloneable
它实现由两点构成的 line。后端目前尚未实现 line 类型,但这个类保证了在实现之后我们就能直接使用它。
变量
public PGpoint point[]
这就是这两个点。
构造器
public PGline(double x1,
double y1,
double x2,
double y2)
参数:
x1 - 第一个点的坐标
y1 - 第一个点的坐标
x2 - 第二个点的坐标
y2 - 第二个点的坐标
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
转换失败时
Overrides:
setValue in class PGobject
public boolean equals(Object obj)
参数:
obj - 要比较的对象
返回值:
如果两条直线相同则为 true
Overrides:
equals in class PGobject
public Object clone()
必须覆盖此方法才能克隆该对象
Overrides:
clone in class PGobject
public String getValue()
返回值:
按 PostgreSQL 所期望语法表示的 PGline
Overrides:
getValue in class PGobject
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 - 第一个点的坐标
y1 - 第一个点的坐标
x2 - 第二个点的坐标
y2 - 第二个点的坐标
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
转换失败时
Overrides:
setValue in class PGobject
public boolean equals(Object obj)
参数:
obj - 要比较的对象
返回值:
如果两条线段相同则为 true
Overrides:
equals in class PGobject
public Object clone()
必须覆盖此方法才能克隆该对象
Overrides:
clone in class PGobject
public String getValue()
返回值:
按 PostgreSQL 所期望语法表示的 PGlseg
Overrides:
getValue in class PGobject
Class org.postgresql.geometric.PGpath
java.lang.Object
|
+----org.postgresql.util.PGobject
|
+----org.postgresql.geometric.PGpath
public class PGpath extends PGobject implements Serializable,
Cloneable
它实现 path(一条多段线,可以是闭合的)
变量
public boolean open
如果路径是开放的则为 true,闭合则为 false
public PGpoint points[]
定义该路径的各个点
构造器
public PGpath(PGpoint points[],
boolean open)
参数:
points - 定义该路径的 PGpoint 数组
open - 如果路径是开放的则为 true,闭合则为 false
public PGpath()
驱动所需
public PGpath(String s) throws SQLException
参数:
s - PostgreSQL 语法的路径定义。
抛出:SQLException
转换失败时
方法
public void setValue(String s) throws SQLException
参数:
s - PostgreSQL 语法的路径定义
抛出:SQLException
转换失败时
Overrides:
setValue in class PGobject
public boolean equals(Object obj)
参数:
obj - 要比较的对象
返回值:
如果两条路径相同则为 true
Overrides:
equals in class PGobject
public Object clone()
必须覆盖此方法才能克隆该对象
Overrides:
clone in class PGobject
public String getValue()
返回按 PostgreSQL 所期望语法表示的该路径
Overrides:
getValue in class PGobject
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
转换失败时
Overrides:
setValue in class PGobject
public boolean equals(Object obj)
参数:
obj - 要比较的对象
返回值:
如果两个点相同则为 true
Overrides:
equals in class PGobject
public Object clone()
必须覆盖此方法才能克隆该对象
Overrides:
clone in class PGobject
public String getValue()
返回值:
按 PostgreSQL 所期望语法表示的 PGpoint
Overrides:
getValue in class PGobject
public void translate(int x,
int y)
按给定的量平移该点。
参数:
x - 在 x 轴上要加的整数增量
y - 在 y 轴上要加的整数增量
public void translate(double x,
double y)
按给定的量平移该点。
参数:
x - 在 x 轴上要加的 double 增量
y - 在 y 轴上要加的 double 增量
public void move(int x,
int y)
把该点移动到给定的坐标。
参数:
x - 整数坐标
y - 整数坐标
public void move(double x,
double y)
把该点移动到给定的坐标。
参数:
x - double 坐标
y - double 坐标
public void setLocation(int x,
int y)
把该点移动到给定的坐标。相关描述参见 java.awt.Point
参数:
x - 整数坐标
y - 整数坐标
参见:
Point
public void setLocation(Point p)
把该点移动到给定的 java.awt.Point。相关描述参见 java.awt.Point
参数:
p - 要移动到的点
参见:
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[]
定义该多边形的各个点
构造器
public PGpolygon(PGpoint points[])
用一个 PGpoint 数组创建多边形
参数:
points - 定义该多边形的各个点
public PGpolygon(String s) throws SQLException
参数:
s - PostgreSQL 语法的多边形定义。
抛出:SQLException
转换失败时
public PGpolygon()
驱动所需
方法
public void setValue(String s) throws SQLException
参数:
s - PostgreSQL 语法的多边形定义
抛出:SQLException
转换失败时
Overrides:
setValue in class PGobject
public boolean equals(Object obj)
参数:
obj - 要比较的对象
返回值:
如果两个多边形相同则为 true
Overrides:
equals in class PGobject
public Object clone()
必须覆盖此方法才能克隆该对象
Overrides:
clone in class PGobject
public String getValue()
返回值:
按 PostgreSQL 所期望语法表示的 PGpolygon
Overrides:
getValue in class PGobject8.7.3. 大对象
大对象在标准的 JDBC 规范中受支持。但是,那个接口是有限的,而 PostgreSQL 提供的 API 允许对对象内容进行随机访问,就像它是一个本地文件一样。
org.postgresql.largeobject 包向 Java 提供了
libpq C 接口的大对象
API。它由两个类组成:LargeObjectManager 处理大对象的创建、打开和删除,而 LargeObject 处理单个对象。
8.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
8.7.3.1.1. 变量
- public static final int SEEK_SET
表示从文件开头定位
- public static final int SEEK_CUR
表示从当前位置定位
- public static final int SEEK_END
表示从文件末尾定位
8.7.3.1.2. 方法
public int getOID()
返回这个
LargeObject的 OIDpublic 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
- 要写入的字节数
8.7.3.2. org.postgresql.largeobject.LargeObjectManager 类
public class LargeObjectManager extends Object java.lang.Object | +----org.postgresql.largeobject.LargeObjectManager
这个类实现了到
PostgreSQL 的大对象接口。它提供的方法允许客户端代码从数据库中创建、打开和删除大对象。打开一个对象时,会返回一个
org.postgresql.largeobject.LargeObject 的实例,然后它的方法就允许访问该对象。
这个类只能由 org.postgresql.Connection 创建。要获得这个类的访问权,使用下面这段代码:
import org.postgresql.largeobject.*; Connection conn; LargeObjectManager lobj; // ... code that opens a connection ... lobj = ((org.postgresql.Connection)myconn).getLargeObjectAPI();
通常,客户端代码会使用 BLOB
方法来访问大对象。但是,有时需要对大对象的更低层访问,这是
JDBC 规范不支持的。
关于如何操纵大对象的内容,请参阅 org.postgresql.largeobject.LargeObject。
8.7.3.2.1. 变量
- public static final int WRITE
- 这个模式表示我们想写入一个对象。
- public static final int READ
- 这个模式表示我们想读取一个对象。
- public static final int READWRITE
- 这个模式是默认值。它表示我们想对一个大对象进行读写访问。
8.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 方法完全相同,提供它是因为 C API 使用 “unlink”。