自己开发O/R Mapping模块其实说来也是挺简单。
第一步, 数据库链接。
关于数据库链接的可移植性这里不多说了,无非工厂,代理之类的东西。
关键在于不同数据库中有些方言的区别,比如SQLServer和MySQL是利用AutoIncrement产生主键,Oracle使用Sequence。不过如果你愿意Oracle也可以使用AutoIncrement,但是Create Table的SQL会有些差别。
另外比较重要的就是Join的语句,当然标准的Inner Join,Left Join,Right Join是都支持的,不过很多习惯Oracle的兄弟们会使用(+),还是MySQL使用(*)的。
最后就是嵌套语句,MySQL可能这方面的支持会稍稍弱一点,不过到5.0已经非常好了。
这些问题其实就是解析你的Bean成为SQL的时候会用到,因此需要多加注意。毕竟最后还是需要用SQL来执行的。姑且我们称之为SQLBuilder,和DataSource一样,我们需要工厂,代理之类的东西来自适应SQLBuilder。换句话说在你使用Oracle的时候会有个OracleSQLBuilder来解析,而使用MySQL的时候会有个MySQLSQLBuilder来解析。
第二步,单表定义
表定义包含2个部分。
一是表名,换句话说就是Bean对应哪个表。
二是属性,每个属性分别对应表中的哪个字段。
写个例子:
class
Car
implements
Serializable
...
{
@Field(name="car_oid", autoincrement=true, sequenceName="seq_car_oid")
private Long oid = null;
@Field(name="name")
private String name = null;

public void setOid(Long oid) ...{
this.oid = oid;
}
public Long getOid() ...{
return this.oid;
}
public void setName(String name) ...{
this.name = name;
}
public String getName() ...{
return this.name;
}
}
这是使用Annotation定义的方式。Field是个Annotation,看看写法。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(
...{ ElementType.METHOD, ElementType.FIELD }
)
public
@
interface
Field
...
{

/** *//**
* 对应的字段域名称
*
* @return
*/
String name();

/** *//**
* 是否是主键
*
* @return
*/
boolean primaryKey() default false;

/** *//**
* 是否自增长
*
* @return
*/
boolean autoIncrease() default false;

/** *//**
* 对应的Sequence名称.<br>
* 此属性只有在autoIncrease为true的时候才生效, 目前只有Oracle数据库会使用这个属性
*
* @return
*/
String sequenceName() default "";

/** *//**
* 是否是时间戳
*
* @return
*/
boolean isTimestampMark() default false;

/** *//**
* 是否是版本号
*
* @return
*/
boolean isVersionMark() default false;
}
有2个声明必须记住: @Retention, 如果不是RUNTIME,那么你在运行态无法获取到这些声明, 自然也就没有办法解析. @Target, 我声明了可以写在Method和Field之前, 你可以根据你的喜好定义.
再看看Table的写法:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public
@
interface
Table
...
{
/** *//**
* 对应的持久化对象名称. 例如表名, 视图名等.
*
* @return
*/
String name();
}
Table的写法和Field差不多, 不过内容少了很多, 主要定义一个表名就行了, 而且是写在类头上的(@Target=TYPE)
当然如果你在1.4或者以前版本的JDK,或者你不喜欢Annotaion,那么以前通常我们用XML定义。
<
car
>
<
property
name
="oid"
autoincrement
="true" sequence="seq_car_oid"
/>
<
property
name
="name"
/>
</
car
>
XML定义可以写在一个文件里,也可以分别写多个文件,就看你的解析器是如何根据Class来寻找的。
其实2种方法都没什么差别,唯一的问题在于使用Annotation的话,你在看这个Bean的时候你就知道数据库的定义了,但是如果用XML定义,那么麻烦你再找一下XML文件在哪里。
看过定义自然程序需要一个解析器来读懂这些定义。这个解析器我就不给例子了,无非是一些通常的代码。

2352

被折叠的 条评论
为什么被折叠?



