Relationship Collection Classes
Relationships with one-to-many or many-to-many cardinality are represented by an object that
implements either the java.util.Set or java.util.Collection interface. The Collection class
is used to access and modify the state of that relationship. We saw some examples of this in an earlier
code example illustrating an OrderHasLineItems relationship. Let's take another look at a fragment
of this code, to examine its use of a relationship collection:
public void addLineItem(LineItemView liv) throws CreateException {
try {
LineItem l = implCreateLineItem(liv.getId(), liv.getProduct(),
liv.getQuantity());
getLineItems().add(l);
} catch (CreateException e) {
e.printStackTrace();
throw e;
}
}
The getLineItems() method is the abstract accessor for the relationship between the order and its
line items. The collection class it returns represents that relationship, and additions to or removals from
the collection class immediately change the relationship. In this case, after we create a new LineItem
component instance, we add that instance to the relationship by adding it to the collection. If we
neglected to add the line item to the collection before we returned from this method, we would have
created a "disconnected" line item entity that was not accessible through the relationship collection. (It
would still, however, be accessible through the query language via finder or ejbSelect() methods.)
The Collection classes that represent a relationship are created exclusively by the EJB container. You
cannot create new instances of these Collection classes, nor can you change the identity of the
Collection class used to represent a particular relationship. The set accessor methods for a relationship
collection do not actually set the collection. Instead, they act in a somewhat counterintuitive manner to
set the contents of the collection based on another relationship collection with the same type of
relationship.
This is a potentially confusing topic that will be covered in depth in the next chapter. For the most part,
when you are working with a relationship that has a multiplicity of many, you will retrieve the
corresponding collection with the get abstract accessor and work directly with that collection, ignoring
the set abstract accessor completely.
Bidirectional Relationships
Relationships that are bi-directional have abstract accessors for both participants in the relationship. For
example, an order entity might have getLineItems() and setLineItems() methods, and a line
item entity object might have a getOrder() method and a setOrder() method. Changes that are
made in one participant in the relationship are instantly reflected in the other participant. For instance,
if you changed the order for a line item within that line item, it would be automatically removed from
the relationship collection for its original order and automatically added to the relationship collection
for its new order within the transaction.
Consider this somewhat facetious code example:
public void doTest() {
Collection lineItems = getLineItems();
Iterator iter = lineItems.iterator();
if (!iter.hasNext()) {
return;
}
LineItem lineItem = (LineItem) iter.next();
The following is, of course, true:
// This is of course true
if (!lineItems.contains(lineItem)) {
throw new IllegalStateException();
}
lineItem.changeOrder();
This will be false, because our collection was updated by the container:
// This is false; the relationship collection
// was automatically updated
if (lineItems.contains(lineItem)) {
throw new IllegalStateException();
}
}
There are many modeling situations that require bi-directional relationships (teacher-student, customer-
order, employee-project, and endless others given the right business requirements). Anyone who has
worked with bi-directional relationships before understands the potential for data-aliasing problems.
What happens if the line item changes its order, but the order doesn't get notified and still thinks that it
owns the line item? Disaster, usually. But you can confidently use bi-directional relationships in your
EJB 2.0 entity beans without worrying about these problems.
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.
|