A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

除了绑定到 XML 文档之外,Castor 还提供了将 Java 数据绑定到 SQL 数据库的能力。这就是所谓的 SQL 数据绑定。定义 SQL 数据绑定
   SQL 数据绑定 也许是一个新的术语,概念其实非常简单。实际上,最好从一个更熟悉的术语 XML 数据绑定 出发来考察。XML 数据绑定就是在 XML 文档数据 — 通常存储在元素和属性中 — 和 Java 对象模型的属性之间建立映射的过程。可以通过编组程序和解组程序在两者之间移动数据。编组程序从 Java 对象模型获得数据存储到 XML 文档中,解组程序从 XML 文档获取数据存入 Java 对象模型的属性中。
在这个基础上,我们说 SQL 数据绑定是在 SQL 数据库数据 — 存储在模式、表、列等中 — 和 Java 对象之间建立映射的过程就毫不奇怪了。编组和解组的过程一样,只不过转换是在 Java 对象和 SQL 而不是 XML 之间进行的。实际上,多数数据绑定文章中如果将 XML 替换为 SQL,元素数据 更改为表记录,讨论的内容就变成了 SQL 数据绑定了。
SQL 数据绑定特别重要的一点是,能够建立 Java 对象到 SQL 数据模式的映射而不需要绑定 Java 或者 SQL 名称。和 XML 相比,关系数据库的结构通常和 Java 对象的结构相距甚远。表是数据的集合,对象通常代表一部分(可能是一行)数据。对象之间的关系必须跟踪到其他对象,就像表之间的关系要跟踪到其他表。但是 Java 对象模型中没有一对多的连接表,当然也没有多对多连接。
即便是中等复杂程度的关系数据库,设计的东西也和对象模型不同。SQL Java 对象之间的映射,大量的工作就是定义对象和表之间的映射。虽然映射可能很复杂,本文中将使用几个简单的映射说明 SQL 数据绑定中映射的基本原理。
Sun 有一个规范叫 Java 数据对象(Java Data ObjectsJDO)。Java Specification Request (JSR) 12JDO 1.0)和 JSR 243JDO 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 {
private String isbn;
private String title;
private List<Author> authors;
public Book() { }
public Book(String isbn, String title, List<Author> 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<Author>();
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<Author> authors) {
this.authors = authors;
}
public List<Author> getAuthors() {
return authors;
}
public void addAuthor(Author author) {
authors.add(author);
}
}
清单 2 Author 类的代码。
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 表
<mapping>
 <class name="ibm.xml.castor.Author" identity="id">
  <map-to table="dw_authors" />
  <field name="id" type="int">
   <sql name="id" type="integer" />
  </field>
  <field name="firstName" type="string">
   <sql name="first_name" type="varchar" />
  </field>
  <field name="lastName" type="string">
   <sql name="last_name" type="varchar" />
  </field>
 </class>
</mapping>
  没有什么新鲜之处,看起来和用于 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 连接方案
<?xml version="1.0" ?>
<!DOCTYPE jdo-conf PUBLIC "-//EXOLAB/Castor JDO Configuration DTD Version 1.0//EN"
"http://castor.org/jdo-conf.dtd">
<jdo-conf>
<database name="YOUR-DATABASE-NAME" engine="mysql">
<driver class-name="com.mysql.jdbc.Driver"
url="jdbc:mysql://YOUR-DATABASE-SERVER-HOSTNAME/YOUR-DATABASE-NAME">
<param name="user" value="YOUR-DATABASE-USERNAME"/>
<param name="password" value="YOUR-DATABASE-PASSWORD"/>
</driver>
<mapping href="sql-mapping.xml"/>
</database>
<transaction-demarcation mode="local"/>
</jdo-conf>
  添加、查找和删除记录
  现在已经做了很多设置工作,终于可以和数据库交互了。利用这些配置文件,需要加载配置、打开数据库然后访问它。清单 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. 向映射文件添加图书信息
<mapping>
<class name="ibm.xml.castor.Book" identity="isbn">
<map-to table="dw_books"/>
<field name="isbn" type="string">
<sql name="isbn" type="varchar" />
</field>
<field name="title" type="string">
<sql name="title" type="varchar" />
</field>
</class>
<class name="ibm.xml.castor.Author" identity="id">
<map-to table="dw_authors" />
<field name="id" type="int">
<sql name="id" type="integer" />
</field>
<field name="firstName" type="string">
<sql name="first_name" type="varchar" />
</field>
<field name="lastName" type="string">
<sql name="last_name" type="varchar" />
</field>
</class>
</mapping>
  没有奇怪的地方,仅仅确定了 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 中的数组
<field name="authors" type="ibm.xml.castor.Author"
collection="arraylist">
</field>
  这很好理解,映射 authors 属性,但其类型是类而不再是 string 或 int。使用 collection="arraylist" 告诉 Castor 该属性是一个集合而不是单值。
  但是现在需要说明该字段要存储作者 ID 以及该字段要存储到哪个表,因为作者 ID 在 dw_books 表中不存在。清单 12 给出了多对多表的名称 — 即 dw_books_authors — 以及该表中图书 ISBN 的键。
  清单 12. 定义多表和多对多关系的 sql 元素
<field name="authors" type="ibm.xml.castor.Author"
collection="arraylist">
<sql name="author_id"
many-table="dw_books_authors"
many-key="book_isbn" />
</field>
   小心地注意其中的逻辑。首先,要记住该元素用于 Book 实例的 authors 属性值。映射的实际字段是 Author 实例,需要找到该对象的标识符部分 — id — 并将其映射到列 author_id。但这不是在 dw_books 表中,因此使用 many-table 表明该表为 dw_books_authors。最后,many-key 属性表明要存储这个 Book 实例的 ISBN 到多对多表中。
  清单 13 显示了包含这部分的完整 sql-mapping.xml 文件。
  清单 13. 为 Books 增加多对多支持
<mapping>
<class name="ibm.xml.castor.Book" identity="isbn">
<map-to table="dw_books"/>
<field name="isbn" type="string">
<sql name="isbn" type="varchar" />
</field>
<field name="title" type="string">
<sql name="title" type="varchar" />
</field>
<field name="authors" type="ibm.xml.castor.Author"
collection="arraylist">
<sql name="author_id"
many-table="dw_books_authors"
many-key="book_isbn" />
</field>
</class>
<class name="ibm.xml.castor.Author" identity="id">
<map-to table="dw_authors" />
<field name="id" type="int">
<sql name="id" type="integer" />
</field>
<field name="firstName" type="string">
<sql name="first_name" type="varchar" />
</field>
<field name="lastName" type="string">
<sql name="last_name" type="varchar" />
</field>
</class>
</mapping>
  测试映射
  清单 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() 调用之外。虽然这只是一个小小的改进,但设想一下添加数百(或数千)本书及其作者的情形。节省不必要的工作至关重要。



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马