实现Castor数据绑定,把 Java 对象绑定到 SQL 数据库

导读:

  级别: 高级

  Brett McLaughlin(brett@newInstance.com), 作家兼编辑, O'Reilly Media Inc.

  2008 年 4 月 30 日

  通过前面的介绍,您已经了解到 Castor 实现 Java? 对象和 XML 之间的转换是多么灵活。Castor 还有更多的功能,包括将这些 Java 对象转化成 SQL 数据库中的行。了解语法上有哪些相同的地方和不同的地方,将 SQL 纳入您的数据绑定工具库中。

  对于多数开发人员 —尤其是各种 Java 版本的用户 —数据绑定已经和闭包、单例(singletons)、Ajax 一样变为常用词汇表中的一部分了。而且和其他术语一样,数据绑定也常常被错误的定义。

  特别是大部分程序员在听到数据绑定的时候,实际上想的是 XML数据绑定。加上这个小小的单词 XML,造成大多数程序员忽略了相当多的功能和灵活性,尤其是如果使用 Castor API 的话。这是因为对于 Castor 而言,XML数据绑定仅仅是其中的一部分。除了绑定到 XML 文档之外,Castor 还提供了将 Java 数据绑定到 SQL 数据库的能力。这就是所谓的 SQL数据绑定。

  定义 SQL 数据绑定

  经常用到的缩写词

  Ajax:异步 JavaScript + XML

  API:应用程序编程接口

  IDE:集成开发环境

  XML:可扩展标记语言

  SQL 数据绑定也许是一个新的术语,概念其实非常简单。实际上,最好从一个更熟悉的术语 XML 数据绑定出发来考察。XML 数据绑定就是在 XML 文档数据 —通常存储在元素和属性中 —和 Java 对象模型的属性之间建立映射的过程。可以通过编组程序和解组程序在两者之间移动数据。编组程序从 Java 对象模型获得数据存储到 XML 文档中,解组程序从 XML 文档获取数据存入 Java 对象模型的属性中。

  在这个基础上,我们说 SQL 数据绑定是在 SQL 数据库数据 —存储在模式、表、列等中 —和 Java 对象之间建立映射的过程就毫不奇怪了。编组和解组的过程一样,只不过转换是在 Java 对象和 SQL 而不是 XML 之间进行的。实际上,多数数据绑定文章中如果将 XML替换为 SQL,元素数据更改为表记录,讨论的内容就变成了 SQL 数据绑定了。

  SQL 数据绑定的意义

  Java 技术刚诞生的时候基本上是一种玩具语言,很大程度上是因为它的 API 非常简单,而且主要关注于图像(还记得 AWT 吗?)。Java 技术走向成熟的标志是 Java 数据库连接(JDBC),能够持久到 SQL 数据库。JDBC 过去(现在也是)惟一的问题是用起来很笨重。并不是说多复杂,而是对于大多数程序而言增加了太多的额外工作。

  使用 Castor 和 SQL 数据绑定可以避免大部分复杂性。更妙的是,这种 API 对于 XML 和 SQL 上下文功能基本相同。而且使用数据绑定,应用程序需要关心的细节也少了。处理 JDBC ResultSet和行数不再是您的代码的问题了,几次简单的编组解组调用就能处理 Java 对象和 SQL 数据库之间的转换。

  关于 SQL 数据绑定可能最有意思的是它没有受到过多的压力和关注。特别是考虑到一大批程序员对 XML 心存芥蒂,说它冗长笨拙,或者他们更愿意使用二进制序列化。但是这些人对 SQL 双手欢迎。事实上,如果发现有一大批程序员甚至真正的程序员也不认为 SQL 是一种合法的数据存储和持久技术,您可能会非常吃惊(看看你周围有多少人认为关系数据库臃肿笨拙、夸大其词或者已经落伍)。

  既然如此,SQL 数据绑定和它的 XML 兄弟相比无疑更有意义。企业应用程序中必然需要持久(或存储)数据,而编写数据访问和检索代码是痛苦的。SQL 数据绑定把一种熟悉的 API(假设您已经阅读过本系列前面的文章)用于 SQL 数据存储。几行命令就能把数据写入表(或者多个表)或者读出来。

  仍然是映射

  SQL 数据绑定特别重要的一点是,能够建立 Java 对象到 SQL 数据模式的映射而不需要绑定 Java 或者 SQL 名称。和 XML 相比,关系数据库的结构通常和 Java 对象的结构相距甚远。表是数据的集合,对象通常代表一部分(可能是一行)数据。对象之间的关系必须跟踪到其他对象,就像表之间的关系要跟踪到其他表。但是 Java 对象模型中没有一对多的连接表,当然也没有多对多连接。

  即便是中等复杂程度的关系数据库,设计的东西也和对象模型不同。SQL 和 Java 对象之间的映射,大量的工作就是定义对象和表之间的映射。虽然映射可能很复杂,本文中将使用几个简单的映射说明 SQL 数据绑定中映射的基本原理。

  这就是 JDO,对吗?

  是。但也不全对。有几分对。这里有点让人费解。

  标准真的很重要吗?

  一些开发人员 —或者他们的老板 —认为使用标准 API 是技术选择中惟一最重要的因素。其他人可能不那么重视。一般来说,最佳选择是采用对您的工作而言效率最高的 API,不论是不是 “标准” API。提高效率重于使用非标准 API 带来的所谓副作用。

  就是说,看看非标准 API 的历史仍然是一种不错的办法。比方说,如果发现一个很好的工具只存在了三个月,是某个家伙在车库里鼓捣出来的,后面可能要面临着升级和支持问题(即便他可能会成为下一个 Bill Gates 或者 Steve Jobs)。如果想选择一个不那么短命的 API,只要看看开发历史是否足够长(2.0 或者更高版本号就是情况良好的信号),最好有一些文档或者在线支持。

  Sun 有一个规范叫 Java 数据对象(Java Data Objects,JDO)。Java Specification Request (JSR) 12(JDO 1.0)和 JSR 243(JDO 2.0)定义了一种非常具体的 SQL 数据绑定方法(虽然从未明确地称为 “SQL 数据绑定”)。如果读过 JDO 然后再读本文开始的介绍部分,就会发现是一件事。但是,Castor 的 JDO(不错,Castor 也叫 JDO,事情更加混乱)不同于 Sun 的 JDO,甚至没有任何关系,只不过两者的基本目标相同而已。

  鉴于可能造成很大混淆,再强调一次:如果使用 Castor 的 JDO,那么它不是Sun 的标准 API。但问题并不像看起来这么糟糕或者简单明了。实际上,Castor 的开发者正努力将其 API 的很多特性纳入 Sun 数据绑定和 JDO API。因此,虽然 Castor 现在还不是标准 API,但很多特性 —包括 API 自身 —可能有一天会成为标准化的 JDO API。

  建立实验环境

  在 XML 数据绑定中,两个端点分别是 Java 对象模型和 XML 文档(实际上是约束文档的 XML 模式)。对于 SQL 数据绑定来说,仍然有 Java 对象模型,不过另一端变成了 SQL 模式:一个或多个表以及表列。本文的例子使用了一组相对比较简单的端点。

  本系列文章一直使用 Java 对象模型表示图书和作者,本文仍然使用同样的数据模型。清单 1显示了 Book类的代码。

  清单 1. Book 类

  



package ibm.xml.castor;

import java.util.LinkedList;

import java.util.List;

public class Book {

/** The book's ISBN */

private String isbn;

/** The book's title */

private String title;

/** The authors' names */

private List authors;

public Book() { }

public Book(String isbn, String title, List authors) {

this.isbn = isbn;

this.title = title;

this.authors = authors;

}

public Book(String isbn, String title, Author author) {

this.isbn = isbn;

this.title = title;

this.authors = new LinkedList();

authors.add(author);

}

public void setIsbn(String isbn) {

this.isbn = isbn;

}

public String getIsbn() {

return isbn;

}

public void setTitle(String title) {

this.title = title;

}

public String getTitle() {

return title;

}

public void setAuthors(List authors) {

this.authors = authors;

}

public List getAuthors() {

return authors;

}

public void addAuthor(Author author) {

authors.add(author);

}

}

  清单 2是 Author类的代码。

  清单 2. 作者类

  



package ibm.xml.castor;

public class Author {

private String firstName, lastName;

public Author() { }

public Author(String firstName, String lastName) {

this.firstName = firstName;

this.lastName = lastName;

}

public void setFirstName(String firstName) {

this.firstName = firstName;

}

public void setLastName(String lastName) {

this.lastName = lastName;

}

public String getFirstName() {

return firstName;

}



public String getLastName() {

return lastName;

}

}

  前面的文章中我们建立了这些类的部分实例并持久到 XML 文档。前两期文章我们关注的是直接从对象模型转换到 XML 文档,两边使用相同的属性名。第三期文章突出 Java 对象和 XML 之间的来回转换,但是允许改变转换前后的命名约定。

  这里我们需要取得类中的所有数据并将其存储到 SQL 数据库。不再是元素和属性,数据要放到列、行和表中。

  建立 SQL 数据库模式

  在某些方面,SQL 数据模式和 Java 对象模型的映射更密切,尤其是如果模型非常简单的话(比如这里的例子)。有两个表:dw_books 和 dw_authors。

  实际上最简单的办法是先建立 dw_authors 表,因为 dw_books 表要引用它。该表包括三列:作者 ID、作者的姓氏和名字。如果按照本文操作的话,可以用 清单 3中的代码在 MySQL 中建立该表。

  清单 3. 作者表

  



CREATE TABLE 'dw_authors' (

'id' INT NOT NULL ,

'first_name' VARCHAR( 50 ) NOT NULL ,

'last_name' VARCHAR( 50 ) NOT NULL ,

PRIMARY KEY ( 'id' ) ,

INDEX ( 'first_name' , 'last_name' )

);

  请注意,本文中所有的表都使用了 dw_前缀,以便于其他表区分开来,特别是 authors和 books都是很常见的表名。虽然可能有点罗嗦,但如果按照本文实验(希望如此)的话这样可以避免与系统中其他数据库的命名冲突。

  接下来是 dw_books 表。这个表也很简单,在 SQL 中创建结构使用的数据定义语言(DDL)如 清单 4所示。

  清单 4. dw_books 表的 DDL

  



CREATE TABLE 'dw_books' (

'isbn' VARCHAR( 13 ) NOT NULL ,

'title' VARCHAR( 200 ) NOT NULL ,

PRIMARY KEY ( 'isbn' ) ,

INDEX ( 'title' )

);

  最后还需要将这两个表联系起来。这就出现了一个问题。一本书可能有多位作者,就是说 dw_books 和 dw_authors 表之间存在多对多的关系。换句话说,一本书可以有多位作者,一位作者可以出版多本书。因此需要一个表连接图书和作者,而且这种连接必须是多对多的。

  在 SQL 中这是很常见的:需要一个连接表,每行包括图书 ISBN 和作者 ID。清单 5显示了表的结构。

  清单 5. 作者和图书的连接表(多对多)

  



CREATE TABLE 'dw_books_authors' (

'book_isbn' VARCHAR( 13 ) NOT NULL ,

'author_id' INT NOT NULL ,

PRIMARY KEY ( 'book_isbn' , 'author_id' )

);

  理解引用完整性

  引用完整性是一个美妙的 SQL 术语,它指的是保持数据库中的所有数据都是干净的,没有错误或者多余的数据,表之间的连接准确合理。对于这个例子来说,它意味着如果删除一本书,那么 dw_books_authors 表中关于该书 ISBN 的所有记录都将被删除。一旦这本书不存在了,它的 ISBN 也不应该有记录。对于作者来说情况一样,删除一位作者,关于其 ID 的所有记录也将被删除。

  为此需要使用外键。因此,dw_books_authors 表中的 book_isbn以 dw_books 表中的 isbn作为外键,dw_books_authors 中的 author_id和 dw_authors 中的 id也存在同样的关系。这样就保证了表间的引用完整性。

  不过多数数据库对引用完整性的处理方式不同,而且 MySQL 很多版本没有提供完整的支持。因此为了简化起见,本文没有使用外键。如果愿意创建外键,当然很好,请参阅数据库厂商提供的文档或者咨询数据库管理员(DBA)。

  设置 SQL 数据绑定

  虽然已经使用 Castor 进行 XML 数据绑定,为了能运行 SQL 数据绑定可能仍然需要稍微修改一下(至少增加一些)编程环境。

  向类路径添加 Castor JDO 文件

  首先需要把 Castor JDO 类放到类路径中。如果已经按照本系列第一期文章(链接参见 参考资料)的说明进行了安装,那么所有的 Castor Java ARchive (JAR) 文件已经在您的机器上了。但是,可能还需要将这些专用的 JDO JAR 文件添加到类路径中。在 Castor 目录下找到 castor-1.1.2.1-jdo.jar 并添加到类路径(您的版本也许更高,但意思一样)。

  这是除了您可能已经放入类路径的其他 Castor JAR 文件之外的,比如 castor-1.1.2.1.jar、castor-1.1.2.1-xml.jar、Xerces 和 Commons Logging JAR 文件。如果使用应用服务器或者 IDE 运行代码,要确保适当修改类路径。

  添加 JDBC 驱动程序

  连接到 SQL 数据库需要 JDBC 驱动程序。用于 Oracle、MySQL、PostgreSQL 等的 JDBC 驱动程序都可免费获得。如果已经存储访问数据库的应用程序,可能已经足够了。否则,用 Google 搜索针对所用数据库的 JDBC 驱动程序,下载 JAR 并添加到类路径中。

  对于本文使用的 MySQL 数据库,需要的 mysql-connector-java-3.0.17-ga-bin.jar 可从 MySQL 网站(详见 参考资料)免费下载。

  将类映射到表

  最简单的 SQL 数据绑定任务:把没有引用其他任何对象的对象映射到一个表。这是 SQL 数据绑定中最基本的操作,其他更高级的功能都是由此演变而来。

  确定映射

  首先将 Author类映射到 dw_authors 表。需要的映射如表 1所示。

  表 1. Author 对象和 dw_authors 表之间的映射

  Java 属性 SQL 列

  firstName first_name

  lastName last_name

  太简单了,不过有一个突出的问题:dw_authors 表还有 id列。事实上这是 dw_authors 表的主键,因此必须有。所以需要稍微修改 Author类,如 清单 6所示。

  清单 6. 为 Author.java 增加 ID

  



package ibm.xml.castor;

public class Author {

private String firstName, lastName;

private int id;

public Author() { }

public Author(int id,String firstName, String lastName) {

this.id = id;

this.firstName = firstName;

this.lastName = lastName;

}

public void setId(int id) {

this.id = id;

}

public int getId() {

return id;

}


public void setFirstName(String firstName) {

this.firstName = firstName;

}

public void setLastName(String lastName) {

this.lastName = lastName;

}

public String getFirstName() {

return firstName;

}



public String getLastName() {

return lastName;

}

}

  现在可以修改显示 Author实例和 dw_authors 表行映射的表格了,如 表 2所示。

  表 2. 添加 ID 字段

  Java 属性 SQL 列

  id id

  firstName first_name

  lastName last_name

  建立 Castor 映射

  现在需要告诉 Castor 哪个 Java 属性映射到哪个 SQL 列。这里使用映射文件,类似于本系列第三期中用于 XML 的映射文件。清单 7显示了用于将 Author实例转化为 dw_authors 行的映射文件。

  清单 7. 把 Author 对象映射到 dw_authors 表

  































  没有什么新鲜之处,看起来和用于 Java 对于与 XML 的映射文件没有什么两样。将该文件保存为 sql-mapping.xml,现在告诉 Castor 如何将 Java 对象属性映射到数据库表。

  标识符属性

  与 Java/XML 映射相比,映射文件中惟一有变化的是使用了 identity属性,用于标识 dw_authors 表的主键字段。以前可能没有使用过 identity属性,因为 Castor 常常自己推断或者根本不需要。但是在 SQL 数据绑定中,该属性让 Castor 知道哪个字段惟一定义了一个对象;该例中是作者的 id字段。

  配置 Castor 进行 SQL 访问

  在 XML 数据绑定中,我们已经介绍了编写代码把 XML 编组为 Java 对象以及反向操作,但是对于 SQL 数据绑定,还有一个软件需要应付:数据库自身。需要告诉 Castor 数据库在哪儿、如何登录以及使用哪个映射文件。这就需要用到配置文件了,通常命名为 jdo-conf.xml。清单 8显示了可用于 MySQL 的配置文件。

  清单 8. 为 Castor 定义 MySQL 连接方案

  





"http://castor.org/jdo-conf.dtd">





url="jdbc:mysql://YOUR-DATABASE-SERVER-HOSTNAME/YOUR-DATABASE-NAME">















  添加、查找和删除记录

  现在已经做了很多设置工作,终于可以和数据库交互了。利用这些配置文件,需要加载配置、打开数据库然后访问它。清单 9完成了这些工作,它创建了一个新的 Author实例,保存到数据库,查找该实例然后删除。

  清单 9. 对作者表使用 SQL 数据绑定

  



import ibm.xml.castor.Author;

import org.exolab.castor.jdo.Database;

import org.exolab.castor.jdo.JDOManager;

public class SQLTester {

public static void main(String args[]) {

try {

JDOManager.loadConfiguration("jdo-conf.xml");

JDOManager jdoManager = JDOManager.createInstance("bmclaugh");

Database database = jdoManager.getDatabase();

database.begin();

Author author = new Author(1001, "Joseph", "Conrad");

database.create(author);

Author lookup = (Author)database.load(Author.class,

new Integer(1001));

System.out.println("Located author is named " +

author.getFirstName() + " " + author.getLastName());

database.remove(lookup);

database.commit();

database.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

  我们来详细的观察一下每个步骤。

  首先需要进行一些初始化工作,加载连接信息并连接到数据库。这个步骤基本上和任何使用 SQL 数据绑定的应用程序一样,因此只需要记住这些命令(或者把本文放入书签):

  

JDOManager.loadConfiguration("jdo-conf.xml");

JDOManager jdoManager = JDOManager.createInstance("bmclaugh");

Database database = jdoManager.getDatabase();

database.begin();

  这里的目的是获得 Database对象实例,它可用于创建、查找和删除记录。得到该实例后就可以创建新的 Author并存储到数据库:

  

Author author = new Author(1001, "Joseph", "Conrad");

database.create(author);

  调用 create()的时候,Castor 将使用映射文件(sql-mapping.xml)来确定如何将传递给该方法的对象存储为 SQL 数据。数据进入数据库,然后就能访问了。

  接下来根据标识符(这就用到了 identity属性)查找对象:

  

Author lookup = (Author)database.load(Author.class,

new Integer(1001));

System.out.println("Located author is named " +

author.getFirstName() + " " + author.getLastName());

  使用 load()方法并传递需要加载的类类型以及记录的标识符值。load()返回一个新实例,可以像其他 Java 对象使用,同样用到了 sql-mapping.xml 定义的映射。

  这个例子删除了新添加的记录,保持数据库原来的状态:

  

database.remove(lookup);

  最后还需要提交修改并关闭数据库:

  

database.commit();

database.close();

  添加关系数据

  可以看到,处理单一的类到表的映射并不难。但是一旦需要处理更加实际的情况,情况就复杂了,比如 Book与 Author实例关联的 Java 对象模型。

  定义基本的图书 SQL 映射

  和 Author一样,也需要在 sql-mapping.xml 中定义将 Book类属性持久到关系数据库的映射。首先增加 清单 10中的代码,它们用于处理图书的基本属性.

  清单 10. 向映射文件添加图书信息

  

















































  没有奇怪的地方,仅仅确定了 Book和映射表(dw_books)以及如何映射对象的属性(isbn和 title)。

  定义多对多关系

  现在情况复杂了:告诉 Castor 图书和作者之间的关系。要记住,关系是这样建立的:

  每本书都有惟一的 ISBN。

  每位作者都有惟一的 ID。

  如果某位作者写了一本书,在 dw_books_authors 建立一条记录包含图书 ISBN 和作者 ID。

  一本书可能有多位作者(dw_books_authors 多条记录的图书 ISBN 相同但作者 ID 不同)。

  一位作者可以写多本书(dw_books_authors 多条记录的作者 ID 相同但图书 ISBN 不同)。

  首先,从 Book类这一侧分析这种关系。对于一个 Book实例,需要用该书的作者填充 authors属性。反之亦然。如果 Book实例的 authors属性有数据,需要将这些作者通过 ID 存入数据库。必须映射该属性— authors—到 dw_books_authors 中的记录。

  为此首先添加另一个 Castor field元素,如 清单 11所示。

  清单 11. 使用 field 元素将 authors 映射为 Books 中的数组

  



collection="arraylist">



  这很好理解,映射 authors属性,但其类型是类而不再是 string或 int。使用 collection="arraylist"告诉 Castor 该属性是一个集合而不是单值。

  但是现在需要说明该字段要存储作者 ID 以及该字段要存储到哪个表,因为作者 ID 在 dw_books 表中不存在。清单 12给出了多对多表的名称 —即 dw_books_authors —以及该表中图书 ISBN 的键。

  清单 12. 定义多表和多对多关系的 sql 元素

  



collection="arraylist">

many-table="dw_books_authors"

many-key="book_isbn" />




  小心地注意其中的逻辑。首先,要记住该元素用于 Book实例的 authors属性值。映射的实际字段是 Author实例,需要找到该对象的标识符部分 —id—并将其映射到列 author_id。但这不是在 dw_books 表中,因此使用 many-table表明该表为 dw_books_authors。最后,many-key属性表明要存储这个 Book实例的 ISBN 到多对多表中。

  清单 13显示了包含这部分的完整 sql-mapping.xml 文件。

  清单 13. 为 Books 增加多对多支持

  





















collection="arraylist">

many-table="dw_books_authors"

many-key="book_isbn" />































  测试映射

  清单 14显示了修改后的 SQLTester,它创建了一个新的 Author和相关的 Book。

  清单 14. 建立新的作者和图书

  



import java.util.Iterator;

import ibm.xml.castor.Author;

import ibm.xml.castor.Book;

import org.exolab.castor.jdo.Database;

import org.exolab.castor.jdo.JDOManager;

public class SQLTester {

public static void main(String args[]) {

try {

JDOManager.loadConfiguration("jdo-conf.xml");

JDOManager jdoManager = JDOManager.createInstance("bmclaugh");

Database database = jdoManager.getDatabase();

database.begin();

Author author = new Author(1001, "Joseph", "Conrad");

Book book = new Book("1892295490", "Heart of Darkness", author);

database.create(author);

database.create(book);

database.commit();

database.begin();

Book lookup = (Book)database.load(Book.class, "1892295490");

System.out.println("Located book is named " + lookup.getTitle());

System.out.println("Authors:");

for (Iterator i = lookup.getAuthors().iterator(); i.hasNext(); ) {

Author bookAuthor = (Author)i.next();

System.out.println(" " + bookAuthor.getFirstName() + " " +

bookAuthor.getLastName());

}

database.commit();

database.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}



  看起来再简单不过了。连接到数据库,创建新的作者和图书,然后保存到数据库(最后以 commit()结束):

  

Database database = jdoManager.getDatabase();

database.begin();

Author author = new Author(1001, "Joseph", "Conrad");

Book book = new Book("1892295490", "Heart of Darkness", author);

database.create(author);

database.create(book);

database.commit();

  剩下的就是检查数据库看看数据是否成功存入了。

  为了更好地模拟实际的数据持久,提交了数据然后启动了一个新事务(提交图书和作者数据之后的第二个 database.begin())。这样可以确保 Castor 数据的本地版本没有被使用,程序的第二部分实际上是查询数据库。

  检验数据

  看看表中的数据是否和预期的一样。表 dw_books 中应该包含 表 3所示的数据。

  表 3. 运行 SQLTester 后 dw_books 中的数据

  isbn 名称

  1892295490 Heart of Darkness

  表 4显示了插入之后的 dw_authors 表。

  表 4. 运行 SQLTester 之后 dw_authors 表中的数据

  id first_name last_name

  1001 Joseph Conrad

  表 5显示了图书和作者之间的连接,从很多方面来说这是迄今您见过的最重要的数据。如果作者和图书不能联系起来,就没有多少用处了。

  表 5. 运行 SQLTester 后 dw_books_authors 多对多表中的数据

  book_isbn author_id

  1892295490 1001

  删除数据

  清单 15这个短小的实用程序删除 SQLTester插入的数据。利用 SQL 数据绑定可以添加图书和作者(绝对应该这样做),与此类似,也可通过更新类来删除这些记录。保持类的独立便于在插入和删除之间检查数据库,这是学习和调试可能出现的任何问题的重要组成部分。

  清单 15. 删除 SQLTester 创建的数据

  



import ibm.xml.castor.Author;

import ibm.xml.castor.Book;

import org.exolab.castor.jdo.Database;

import org.exolab.castor.jdo.JDOManager;

public class SQLClean {

public static void main(String args[]) {

try {

JDOManager.loadConfiguration("jdo-conf.xml");

JDOManager jdoManager = JDOManager.createInstance("bmclaugh");

Database database = jdoManager.getDatabase();

database.begin();

try {

Book book = (Book)database.load(Book.class, "1892295490");

database.remove(book);

} catch (org.exolab.castor.jdo.ObjectNotFoundException ignored) { }

try {

Author author = (Author)database.load(Author.class, 1001);

database.remove(author);

} catch (org.exolab.castor.jdo.ObjectNotFoundException ignored) { }

database.commit();

database.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}



  其中嵌入了应对没有可供删除的数据这种情况的异常处理语句,使得程序更健壮一点。

  Castor 自身不能持久关系

  观察 SQLTester(清单 14),值得注意的是 Author和 Book的实例都持久到了数据库。实际上如果访问其中一个就只能得到图书或者作者,而看不到 dw_books_authors 中的任何数据。

  对于 Java 程序员来说,这似乎有点奇怪。如果一个 Book实例有 Author,这两者难道没有联系在一起吗?没有作者的图书也能持久吗?不错,Castor 允许这种情况,而且这是它的默认行为。但是,如果希望 Castor 保持这种联系,可使用下列命令:

  

database.setAutoStore(true);

  该命令必须在创建任何事务之前发出,因此 清单 16在 清单 14的基础上略加修改来完成这项操作。

  清单 16. 自动存储关系的测试程序

  



import java.util.Iterator;

import ibm.xml.castor.Author;

import ibm.xml.castor.Book;

import org.exolab.castor.jdo.Database;

import org.exolab.castor.jdo.JDOManager;

public class SQLTester {

public static void main(String args[]) {

try {

JDOManager.loadConfiguration("jdo-conf.xml");

JDOManager jdoManager = JDOManager.createInstance("bmclaugh");

Database database = jdoManager.getDatabase();

database.setAutoStore(true);

database.begin();

Author author = new Author(1001, "Joseph", "Conrad");

Book book = new Book("1892295490", "Heart of Darkness", author);

// We can persist just the book, and Castor will handle the author, as well

// database.create(author);


database.create(book);

database.commit();

database.begin();

Book lookup = (Book)database.load(Book.class, "1892295490");

System.out.println("Located book is named " + lookup.getTitle());

System.out.println("Authors:");

for (Iterator i = lookup.getAuthors().iterator(); i.hasNext(); ) {

Author bookAuthor = (Author)i.next();

System.out.println(" " + bookAuthor.getFirstName() + " " +

bookAuthor.getLastName());

}

database.commit();

database.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}



  试一下(如果数据库中还有数据首先运行 SQLClean),就会得到和原来相同的结果 —除了新增的 database.create()调用之外。虽然这只是一个小小的改进,但设想一下添加数百(或数千)本书及其作者的情形。节省不必要的工作至关重要。

  结束语

  虽然 XML 数据绑定已经非常稳定,在很大程度上不是增加而是修改,JDO —包括 Sun 和 Castor 版本 —仍然是一种通用的 API。但是,这并不意味要避免使用它,因为 SQL 数据绑定和 JDO(无论哪个厂商)都可以简化您的编程工作。以本文作为起点而不是权威性的指南来学习这一技术。

  尝试一下 SQL 数据绑定看看是否有助于您的应用程序开发(这基本上是必然的)。然后比较一下 Sun 和 Castor 的 JDO 看看喜欢哪一种。最后选择一种使用。即便 Castor 的版本不是标准的,但是更加灵活,而且随着更深地参与 Sun,将来有一天官方标准可能纳入 Castor 的很多特性。

  最重要的是,编程更加轻松。SQL 数据绑定可以帮助您提高效率,降低开发周期,最终提高您的工作质量以及所开发应用程序的质量。在同一个应用程序中使用 SQL 和 XML 数据绑定,两者采用了同样的映射范型。您将从中受益,也许最终会完全放弃 JDBC,没有人认为这样不好。

  下载

  描述 名字 大小 下载方法

  Java 源代码 javaSourceCode.zip 3KB

  Castor 配置文件 castorConfigurationFiles.zip 1KB

  参考资料

  学习

  您可以参考本文在 developerWorks 全球站点上的 英文原文。

  实现 Castor 数据绑定,第 1 部分:安装和设置 Castor(Brett McLaughlin,developerWorks,2007 年 11 月):本系列的第一期文章介绍了如何下载、安装、设置、配置 Castor 以及类路径问题等等,以便在您的机器上运行它。

  实现 Castor 数据绑定,第 2 部分:编组和解组 XML(Brett McLaughlin,developerWorks,2007 年 12 月):学习如何把 Java 类转换成 XML,然后再把 XML 转换回 Java 代码,以及 Castor 的工作原理,如何保证类的设计适应这种 API。

  实现 Castor 数据绑定,第 3 部分: 模式之间的映射(Brett McLaughlin,developerWorks,2008 年 1 月):使用 Castor 将任意或者特殊格式的 XML 文档数据转换成自定义的 Java 对象。不再受制于 XML 文档的元素名或者 Java 类的变量名。

  Castor 网站:了解 Castor 的各种信息。

  Castor 类:阅读 JavaDoc。

  Introduction to Castor JDO:详细介绍了这种对象-关系映射和数据绑定框架。

  Sun 的 Java Data Objects 页面:访问 JDO 官方版本的信息中心。

  JSR12:该规范定义了最初的 Java 数据对象 JDO 1.0。

  JSR243:关于 JDO 2.0 的规范强调了 JDO 的易用性,标准化了 JDO 数据库支持,拓宽了 JDO 的范围。

  Castor JDO 入门(Bruce Snyder,developerWorks,2002 年 8 月):阅读这篇早期的 developerWorks 文章。尽管文中的一些代码已经过时,但是其中的概念仍然适用。

  数据绑定实践:涉入真实世界(Brett McLaughlin,,developerWorks,2004 年 5 月):这是一组系列文章的第一部分,介绍了 Sun 的数据绑定 API,JAXB。

  IBM XML 认证:了解如何才能成为一名 IBM 认证的 XML 及相关技术的开发人员。

  XML 技术库:developerWorks XML 专区提供了大量技术文章和技巧、教程、标准以及 IBM 红皮书。

  developerWorks XML 专区:了解 XML 的方方面面。

  developerWorks 技术事件和网络广播:随时关注技术的最新进展。

  技术书店:关于本文主题和其他技术主题的书籍。

  Podcasts:倾听 IBM 技术专家的讲座。

  获得产品和技术

  MySQL JDBC 驱动程序:从 MySQL.com 下载和了解这种原生 Java JDBC 支持。

  Java and XML, Third Edition(Brett McLaughlin 和 Justin Edelson,O'Reilly Media, Inc.):全面掌握 XML,包括关于数据绑定和映射的扩展信息。

  Java and XML Data Binding(Brett McLaughlin,O'Reilly Media, Inc.):在这部早期的著作中可以找到 Castor 的一些详细信息,以及数据绑定涉及的概念。

  Castor Professional Services:您正在寻求关于 Castor 的付费支持或帮助吗?请了解一下 Castor 的专业服务。

  IBM 试用软件:用这些试用软件开发您的下一个项目,可直接从 developerWorks 下载。

  讨论

  参与论坛讨论。

  XML 专区讨论论坛:参与和 XML 有关的讨论。

  developerWorks XML 专区:分享您的观点:阅读本文后在这个论坛上提交您的见解和建议。XML 专区编辑负责该论坛,欢迎您的参加。

  developerWorks blogs:访问这些 blog,加入 developerWorks 社区。

  关于作者

  Brett McLaughlin 的著作上过畅销榜并获得过非小说类图书奖。他著述丰富,包括计算机编程、家庭暴力、分析和设计,总印数超过 100,000。他编写、编辑和出版技术书籍快十年了,除了使用字符处理器外,他还喜欢弹奏吉他、和两个儿子在屋子里追逐嬉闹、和妻子观看重新开播的 Arrested Development。他的新著 Head First Object Oriented Analysis and Design荣获 2007 Jolt Technical Book 大奖。经典著作 Java and XML仍然是关于在 Java 语言中使用 XML 技术的权威书籍。



本文转自

http://www.ibm.com/developerworks/cn/xml/x-xjavacastor4/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值