[ Team LiB ] |
8.2 Persistence ApproachAs you have seen with all of the other automated persistence systems in this book, Castor and Hibernate both persist component attributes by reading an XML configuration file that defines persistence mapping. Table 8-1 shows the attributes of two business objects we might want to persist to a database.
Example 8-1 contains the code for the Author class described in Table 8-1. Example 8-1. A persistent Author classpackage book; public class Author { private long authorID; private String firstName; private String lastName; private Set publications; public long getAuthorID ( ) { return authorID; } public String getFirstName( ) { return firstName; } public String getLastName( ) { return lastName; } public Set getPublications ( ) { return publications; } public void setAuthorID (long id) [ authorID = id; } public void setFirstName(String fn) { firstName = fn; } public void setLastName(String ln) { lastName = ln; } public void setPublications (Set pubs) { publications = pubs; } } This business class is very simple—nothing but getters and setters to manage the attributes. No persistence code is present. Example 8-2 contains the basic code for the Book class. Example 8-2. Book value object that contains an Author value object referencepackage book; public class Book { private Author author; private long bookID private String title; public Author getAuthor ( ) { return author; } public long getBookID ( ) { return bookID; } public String getTitle ( ) { return title; } public void setAuthor (Author auth) { author = auth; } public void setBookID (long id) { bookID =id; } public String setTitle (String ttl) { title = ttl; } } 8.2.1 Castor Field MappingThe key to Castor and Hibernate persistence is the XML file. Each API has it own definition language for defining the mapping between objects and a table. Example 8-3 shows how Castor maps the business objects to a database. Example 8-3. Castor XML mapping descriptor<?xml version="1.0"?> <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor. exolab.org/mapping.dtd"> <mapping> <class name="book.Author" identity="authorID" key-generator="MAX"> <map-to table="AUTHOR"/> <field name="authorID" type="long"> <sql name="AUTHORID"/> </field> <field name="firstname" type="java.lang.String"> <sql name="FIRSTNAME"/> </field> <field name="lastname" type="java.lang.String"> <sql name="LASTNAME"/> </field> <field name="publications" type="book.Book" collection="set"> <sql many-key="authorid"/> </field> </class> <class name="book.Book" identity="bookID" key-generator="MAX"> <map-to table="BOOK"/> <field name="bookID" type="long"> <sql name="BOOKID"/> </field> <field name="title" type="java.lang.String"> <sql name="TITLE"/> </field> <field name="author" type="book.Author"> <sql name="AUTHORID"/> </field> </class> </mapping> For each class you wish to map, you have a class[2] entry in your XML-descriptor. This tag identifies the following:
Castor supports the following key generation algorithms:
The SEQUENCE and HIGH-LOW algorithms require parameters. You can specify the parameters using the key-generator tag outside the class tag: <key-generator name="HIGH-LOW"> <param name="table" value="Sequence"/> <param name="key-column" value="name"/> <param name="value-column" value="seed"/> <param name="grab-size" value="1000000"/> </key-generator>
Within the <class></class> enclosure is the set of tags that defines the mapping of class attributes to database tables. The first tag in the group is the map-totable tag. As its name suggests, it specifies the name of the database table to which the attributes of this class map. The rest of the tags define the actual field-to-column mappings. The tag of special interest is the one that defines how an Author relates to Book. Instead of identifying a column in the AUTHOR table, it identifies an attribute in the Book class. Castor then uses the mapping of this column to perform the appropriate joins. 8.2.2 Hibernate Field MappingField mapping in Hibernate is quite similar. Example 8-4 shows the XML descriptor that defines that mapping of the sample classes to a database. Example 8-4. Hibernate XML mapping descriptor<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http:// hibernate.sourceforge.net/hibernate-mapping-1.1.dtd"> <hibernate-mapping > <class name="book.Author" table="AUTHOR"> <id name="authorID" column="AUTHORID" type="long"> <generator class="vm.long"/> </id> <property name="firstname" column="FIRSTNAME" type="string"/> <property name="lastname" column="LASTNAME" type="string"/> <set role="publications" lazy="true"> <key column="AUTHORID"/> <one-to-many class="book.Book"/> </set> </class> <class name="book.Book" table="BOOK"> <id name="bookID" column="BOOKID" type="long"> <generator class="vm.long"/> </id> <property name="title" column="TITLE"/> </class> </hibernate-mapping> The Hibernate code is similar to the Castor code, yet different in many important ways. Again, Hibernate uses a class tag to define the persistence mapping for a specific Java class. Unlike Castor, Hibernate defines the table mapping as a tag attribute. Within a class, you identity the ID, properties, and sets of the class. The ID is the primary key field. The id tag contains a generator tag to specify a key generation algorithm to use for automated key generation. This tag identifies a Java class that performs a key generation algorithm. If the algorithm requires parameters, they may be specified in the body of the generator tag as param tags: <generator class="org.dasein.persist.Sequence"> <param>sequence</param> </generator> The generator class is an implementation of cirrus.hibernate.id.IdentifierGenerator. Hibernate provides the following built-in generators:
Properties are the basic attributes of the class. Sets, on the other hand, represent the one-to-many or many-to-many mappings for the class. Again, our objects map one author to many books. Hibernate captures this relationship through the set tag. Hibernate supports six different collection tags:
For all of these set types except arrays, you can enable lazy-loading through the lazy="true" attribute. Using lazy-loading can greatly increase the speed of your application for operations such as searching. Additional approaches such as caching can also greatly increase the speed of your application. It is worthy to note that most alternative persistence APIs offer some type of built-in object caching that can be turned on or off.
|
[ Team LiB ] |