Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Enterprise JavaBeans™ Specification, Version 2.0 - Sun Microsystems.pdf
Скачиваний:
14
Добавлен:
24.05.2014
Размер:
2.71 Mб
Скачать

Sun Microsystems Inc

The entity bean provider’s view of persistence Enterprise JavaBeans 2.0, Public Draft Entity Bean Component Contract for Container

In the case of a many-to-many relationship, if the value of a cmr-field is assigned to a cmr-field of the same relationship type in another instance, the objects in the collection of the first instance are assigned as the value of the cmr-field of the second instance. The objects contained in the two collections are the same; however, the two collection objects themselves are not. That is, the contents of the collections are shared, but not the collections themselves. If, for example, there is a many-to-many relationship between customers and sales representatives, assigning the set of customers of one sales representative to the other will resulting in both sales representatives handling the same set of customers. Thus, if the first sales representative originally handled a different set of customers, those customers will no longer be handled by that sales representative.

public void shareCustomers(SalesRep rep) { setCustomers(rep.getCustomers());

// the customers are shared among the salesreps

}

The elements of a collection-valued cmr-field that participates in a many-to-many relationship may be treated as individuals by using the methods of the java.util.Collection API. For example, a customer may be added to or removed from the set of customers handled by a particular sales representative without affecting the set of customers handled by the other.

In the case of a collection-valued cmr-field in a one-to-many relationship, in order to reassign an element of one collection to another collection, the element must be removed from the first collection and then added to the second. Thus, in the case of the relationship between Address and TelephoneNumber, an individual telephone number may be reassigned from one address to another by removing it from the set of telephone numbers for the first address and adding it to the collection of telephone numbers for the second. Alternatively, if the relationship is bidirectional, the same effect can be achieved by setting the value for the address in the individual telephone number object instance to the new address. The Persistence Manager must detect any attempt to share an element of a one-to-many relationship across a one-to-many relationship of the same relationship type of a different instance and raise the javax.lang.IllegalArgumentException.

9.4.6 Collections managed by the Persistence Manager

The collections that are used in the representation of one-to-many and many-to-many container managed relationships are implemented and managed by the Persistence Manager. The following semantics apply to these collections:

There is no constructor available to the Bean Provider for the collections that are maintained by the Persistence Manager.

If there are no related values for a given cmr-field, the get accessor method for that cmr-field returns an empty collection (not null).

Assigning null as the value of a collection-valued cmr-field causes the cmr-field to have the empty collection as its value.

The Bean Provider cannot assign an arbitrary collection instance to a collection-valued cmr-field. It is the responsibility of the Persistence Manager to detect the attempt to do this and

117

5/31/00

Sun Microsystems Inc.

Entity Bean Component Contract for Container Managed PersistenceEnterprise JavaBeans 2.0, Public Draft The entity bean provider’s

to raise the java.lang.IllegalArgumentException. For example, the following attempt to assign to the lineItems cmr-field results in an IllegalArgumentException:

...

Vector v = new Vector();

v.add(lineitem);

setLineItems(v);

...

9.4.7 Dependent value classes

A dependent value class can only be the value of a cmp-field, not a cmr-field. A dependent value class cannot have a member that is a dependent object class. A dependent value class can always be assigned to a cmp-field of the corresponding dependent value class type. The get accessor method for a cmp-field that corresponds to a dependent value class returns a copy of the dependent value class instance. The assignment of a dependent value class value to a cmp-field causes the value to be copied to the target cmp-field.

Dependent value classes that are referred to through container managed persistent fields must be serializable.

Descriptors for dependent value classes must not be specified in the deployment descriptor.

9.4.8 Non-persistent state

The Bean Provider may use instance variables in the entity bean instance to maintain the non-persistent state of the entity bean, e.g., a JMS connection.

The Bean Provider can also use instance variables to store values that depend on the persistent state of the entity bean or its dependent objects, although this use is not encouraged. If this is done, the Bean Provider must use the ejbLoad() method to resynchronize the values of any instance variables that depend on the entity bean’s persistent state, such as references to dependent objects or collections of dependent objects. In general, any non-persistent state that depends on the persistent state of an entity bean or its dependent objects must be recomputed during the ejbLoad() method.

9.4.9 The relationship between the persistence view and the client view

The Enterprise Java Beans architecture defines a component model in which the client view of the component hides the details of the internal implementation of the enterprise bean class. Typically, after designing the client view of an entity bean, the bean provider will design the internals of the component, deciding on its abstract persistence schema. Therefore, the classes that are exposed by the remote interface of the bean may or may not be related to the classes that require persistence. In designing the abstract persistence schema of the bean, the Bean Provider should therefore keep in mind the following:

The classes and relationships that are exposed by the remote interface are decoupled from the persistence layer. Instances of these classes are passed to and from the client by value.

5/31/00

118

Sun Microsystems Inc

The entity bean provider’s view of persistence Enterprise JavaBeans 2.0, Public Draft Entity Bean Component Contract for Container

The classes and relationships that are defined in the abstract persistence schema are persistent in nature. The concrete representation of these classes and relationships (including the Collection types) is determined by the persistence manager that is used in the given deployment environment.

Because the persistence manager is free to optimize the delivery of persistent data to the bean instance (for example, by the use of lazy loading strategies), the instances of the dependent object classes that are defined in the abstract persistence schema and the contents of collections managed by the persistence manager may not be fully materialized.

The Bean Provider must therefore never expose the dependent object classes that comprise the abstract persistent schema of an entity bean in the remote interface of the bean. Likewise, the bean provider must never expose the persistent Collection classes that are used in container manager relationships.

For the same reasons, the get and set methods of the entity bean’s abstract persistence schema must not be exposed through the remote interface of the entity bean except in the following cases:

When the relationship is a one-to-one or many-to-one relationship between two entity beans and is defined as such in the deployment descriptor.

For a cmp-field , the get method that returns the value of the cmp-field and the corresponding set method may be exposed.

Dependent value classes can be exposed in the remote interface and can be included in the client ejb-jar file. The Bean Provider is likewise free to expose get and set methods that do not correspond to the container managed persistent fields and relationships of the entity bean’s abstract persistent schema.

In the case of dependent object classes, which cannot be exposed in the remote interface, the Bean Provider can use the accessor methods to obtain instances of these persistent classes (including the collection classes that correspond to relationships), and can then copy data to or from those instances to instances of the classes that are exposed in the remote interface.

9.4.10 Mapping data to a persistent store

There are many techniques that the user of the Persistence Manager Provider’s tools can use to map an entity bean and its dependent object classes onto a persistent store. The EJB specification does not prescribe how this is done.

9.4.11 Example

Figure 21 illustrates an entity bean Order with relationships to line items, credit cards, customers and products. It shows the abstract persistence schema and relationships. The accessor methods for the dependent object classes are not shown. Sample code for the OrderBean class follows the figure.

119

5/31/00

Sun Microsystems Inc.

Entity Bean Component Contract for Container Managed PersistenceEnterprise JavaBeans 2.0, Public Draft The entity bean provider’s

Figure 21 Relationship example

5/31/00

120

Sun Microsystems Inc

The entity bean provider’s view of persistence Enterprise JavaBeans 2.0, Public Draft Entity Bean Component Contract for Container

The sample code below illustrates how the relationships and the accessor methods of the Order entity bean’s abstract persistence schema are used. The code also illustrates the use of the dependent object classes LineItem and CreditCard. The dependent value class ClientLineItem is used only in the client view.

package com.acme.order;

import java.util.Collection; import java.util.Vector; import java.util.Date;

...

public abstract class OrderBean implements javax.ejb.EntityBean{

private EntityContext context;

// define codes for processing

static final int BACKORDER = 1; static final int SHIPPED = 2; static final int UNSHIPPED = 3;

//

....

// getters and setters for the cmp fields

public abstract int getOrderStatus();

public abstract void setOrderStatus(int orderStatus);

public abstract boolean getCreditApproved();

public abstract void setCreditApproved(boolean creditapproved);

public abstract Date getOrderDate();

public abstract void setOrderDate(Date orderDate);

// getters and setters for the relationship fields

public abstract Collection getLineItems();

public abstract void setLineItems(Collection lineitems);

public abstract Customer getCustomer();

public abstract void setCustomer(Customer customer);

public abstract CreditCard getCreditCard();

public abstract void setCreditCard(CreditCard creditcard);

// methods to create instances of dependent object classes

public abstract CreditCard createCreditCard(); public abstract LineItem createLineItem();

//business methods.

//Remote method setCustomerForOrder:

121

5/31/00

Sun Microsystems Inc.

Entity Bean Component Contract for Container Managed PersistenceEnterprise JavaBeans 2.0, Public Draft The entity bean provider’s

public void setCustomerForOrder(Customer customer, String creditcardNum, String creditCardType, String expiration)

throws InvalidCreditCardException{

// CreditCard is a dependent object created by the entity bean

CreditCard card = createCreditCard(); card.setNumber(creditcardNum); card.setType(creditCardType); card.setExpires(convertToDate(expiration)); if (valid(card)) {

setCustomer(customer);

setCreditCard(card); } else {

throw new InvalidCreditCardException();

}

}

//remote method addLineItem:

//This method is used to add a line item.

//Internally the bean code creates the dependent persistent

//object and adds it to the collection of lineitems that

//are already created.

public void addLineItem(Product product, integer quantity, AddressToShip address)

throws InsufficientInfoException{

// create a new line item

if (validAddress(address)) {

//AddressToShip is a legacy class. It is a dependent

//value class that is available both in the client and

//in the entity bean, and is serializable.

//We will use the address directly for the line item

//and its persistent representation.

LineItem litem = createLineItem(); litem.setProduct(product); litem.setQuantity(quantity); litem.setTax(calculateTax(product.getPrice(),

quantity,

address));

litem.setStatus(UNSHIPPED);

//set the address for the line item to be shipped litem.setAddress(address);

//Entity bean uses a special dependent value class to

//represent the dates representing the order status.

//This class holds shipment date, expected shipment,

//creditapproval date, inventory dates which are

//internal to the order fullfillment process.

//Not all information represented in this class

//will be available to the client when

//the client requests to see the line items.

5/31/00

122

Sun Microsystems Inc

The entity bean provider’s view of persistence Enterprise JavaBeans 2.0, Public Draft Entity Bean Component Contract for Container

Dates dates = new Dates(); litem.setDates(dates); getLineItems().add(litem);

} else {

throw new InsufficientInfoException();

}

}

//remote method getOrderLineItems:

//This method makes a view of the lineitems that are in this

//order available in the client. It makes only the relevant

//information visible to the client and hides the internal

//details of the representation of the lineitem

public Collection getOrderLineItems() { Vector clientlineitems = new Vector(); Collection lineitems = getLineItems();

java.util.Iterator iterator = lineitems.iterator();

//ClientLineItem is a value class that is available in the

//client and represents the client view of the persistent

//dependent object LineItem. It is not an abstract class.

//The entity bean provider abstracts from the persistent

//representation of the line item to construct the client

//view

ClientLineItem clitem;

while (iterator.hasNext()) {

LineItem litem = (LineItem)iterator.next(); clitem = new ClientLineItem();

//only the name of the product is available in the

//client view

clitem.setProduct(litem.getProduct().getName()); clitem.setQuantity(litem.getQuantity());

//the client view gets a specific descriptive message

//depending on the line item status. clitem.setCurrentStatus(

statusCodeToString(litem.getStatus()));

//address is not copied to the client view.

//as this class includes other information with

//respect to the order handing that should not be

//available to the client. Only the relevant info

//is copied.

int lineitemStatus = litem.getStatus(); if ( lineitemStatus == BACKORDER) {

clitem.setShipDate( litem.getDates().getExpectedShipDate());

} else if (lineitemStatus == SHIPPED) { clitem.setShipDate(

litem.getDates().getShippedDate());

}

//add the new line item

123

5/31/00