iihero原创,如若转载,请务必注明出处。
数据库发展到今天, RDBMS( 关系型数据库管理系统 ) 和 ODBMS( 对象数据库管理系统 ) 的界限已经变得模糊了,取而代之的是 ORDBMS( 对象关系型数据库管理系统 ) ,对此, Oracle 和 DB2 早年前都给出了自己的解决方案,即采用类似以下的抽象语法:
create type Point is object
(
x int,
y int,
......
)
Sybase ASE 数据库,发展到现在 15.0.3 ,在语法上,似乎并没有对这种抽象语法的直接支持。它采取的是另一种解决方案,即可以由用户直接定义一个 Java 类,让这个 Java 类直接成为一种抽象类型。那就是 Sybase ASE 数据库的 Java 服务选件,它是一种功能非常强大的组件。
比如,我们要提供一个解决方案,直接支持二维点 Point 类型的存取。怎么实现呢?
<!-- [if !supportLists]-->
<!-- [endif]-->
确定你的 ASE 数据库安装并拥有 Java Options 选项,如何得知呢?从 Sybase Central ,连接到 ASE 服务器,右键 à 属性 à 版本 à 详细信息,可以得到如下信息: ASE_JAVA ,有相应的版本和有效期信息,示例如下图,它支持 Java ,有效期到 2020 年 1 月 20 日 。
除此以外,还得让服务器启动时也支持 Java 。
D:\ASE150>isql -Usa -Psybase1
1> sp_configure "enable java", 1
2> go
(1 row affected)
配置选项改变 . 因为选项是静态的 ,Adaptive Server 必须重启 , 以使改动生效 .
如果将 'enable java' 更改为 '1' , ASE 使用的内存量就能增加 580K 。
(return status = 0)
然后重启 Sybase ASE 数据库,即可生效,开始完全支持 Java 。
首先,实现 Point 类。 ASE 支持 Java 对象类型,有一个条件,它必须实现了序列化接口。同时,编译为 class 文件时,编译的目标版本最好是 1.1( 为了保持兼容 ) 。
Point 类的一个简单实现如下:
public class Point implements java.io.Serializable
{
private static final long serialVersionUID = -2550063311147977493L;
public double _x;
public double _y;
public Point()
{
_x = 0;
_y = 0;
}
public Point(double x, double y)
{
_x = x;
_y = y;
}
public Object clone()
{
return new Point(_x, _y);
}
public String toString()
{
return "(" + _x + ", " + _y + ")";
}
public static double distance(Point a, Point b)
{
return (double)Math.sqrt((a._x - b._x)*(a._x - b._x)
+ (a._y - b._y)*(a._y - b._y));
}
public static void main(String[] args)
{
Point a = new Point(1.0, 1.0);
Point b = new Point(5.0, 4.0);
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println(Point.distance(a, b));
}
}
设定好 jdk 路径和 classpath 之后 , 编译打包:
javac -g -target 1.1 *.java
jar -cvf0 Point.jar *.class
装载 java 包到目标数据库
如下图所示:进入具体的数据库 iihero à Java 对象 à Jar 文件,右键 à 新建,即可把刚才打好的 java 包 Point.jar 装载到数据库 iihero 当中。
面向对象应用的实际效果
D:\ASE150>isql -Uspring -Pspring1
1> use iihero
2> go
创建含对象类型 Point 列的表:
1> create table testpoint(id int primary key, p Point)
2> go
使用对象特性插入数据并查询:
1> insert into testpoint values (1, new Point(1.0, 1.0))
2> insert into testpoint values (2, new Point(5.0, 4.0))
3> insert into testpoint values (3, new Point(6.0, 13.0))
4> go
(1 row affected)
(1 row affected)
(1 row affected)
1> select * from testpoint
2> go
id p
----------- --------------------------------------------------
1 (1.0, 1.0)
2 (5.0, 4.0)
3 (6.0, 13.0)
(3 rows affected)
直接取属性值:
1> select id, p>>_x, p>>_y from testpoint
2> go
id
----------- --------------------------- ---------------------------
1 1.000000 1.000000
2 5.000000 4.000000
3 6.000000 13.000000
(3 rows affected)
查询两点间的距离:
1> select a.id, b.id, Point.distance(a.p, b.p) from testpoint a, testpoint b whe
re a.id < b.id
2> go
id id
----------- ----------- ---------------------------
1 2 5.000000
1 3 13.000000
2 3 9.055385
(3 rows affected)
以距离作为条件查询点 ( 查询两点间距离小于 6.0 的点对 ) :
1> select a.id, b.id from testpoint a, testpoint b where Point.distance(a.p, b.p
) <6.0 and a.id > b.id
2> go
id id
----------- -----------
2 1
(1 row affected)
<!-- [if !supportLists]-->二、 <!-- [endif]-->总结
在到 ASE 数据库服务器内部,它对 Java 类作了如下映射:
select 出对象列的值,就是 Java 对象的 toString() 值。
静态方法可以直接在 select 语句里当作函数进行调用,如上例中的 Point.distance() 方法
直接可以取类的成员值,如果那个成员是公有成员,并且有相应的 SQL 类型映射,如上例中的 p>>_x, p>>_y ,使用 ”>>” 操作符来提取。
按照上述原理,用户完全使用内置的 Java 包实现非常复杂的逻辑,然后在 SQL 语句中直接加以利用。尤其是那种接近于面向对象数据库的应用。
总之,使用内置 Java 支持对对象类型的存取,是一种很直观易用的方法,也便于用户进行扩充。从这个角度来看, Sybase ASE 也可以算是支持面向对象的数据存取了。