Previous Next vertical dots separating previous/next from contents/index/pdf

Relationships in Entity Beans

Entity relationships in CMP entity beans are used to model real-world dependencies between business concepts. This topic gives an overview of the seven relationship types, and for each of these relationships describes implementation details in the EJBs and the underlying database tables.

For more detailed information, see the WebLogic Server documentation on Using Container-Managed Relationships and Defining Container-Managed Relationships. Note that much of the WebLogic Server documentation describes these concepts in the context of EJB descriptors, which are automatically generated by Workshop for WebLogic.

Each of the sections in this topic focuses on a relationship type:

One-to-One, Unidirectional

In a one-to-one unidirectional relationship, object A relates to object B. In addition, given object A you can find a reference to object B, but not the other way around. An example of such a relationship is between a concertgoer and a ticket, assuming the perspective of the ticket counter. Each concertgoer requires exactly one ticket, and the concertgoer will have a reference to her ticket. However, given a ticket you don't know the concertgoer. That is, if a lost ticket is returned to the ticket counter, it is not possible to trace it back to the concertgoer.

Here's how the @Relation annotation on the Concertgoer bean might look:

@Relation(roleName = "ConcertgoerHasTicket", 
    cmrField = "ticket", 
    targetEjb = "Ticket", 
    multiplicity = Relation.Multiplicity.ONE, 
    name = "Concertgoer-Ticket")
abstract public class Concertgoer
    extends GenericEntityBean
    implements EntityBean

Here's how the @Relation annotation on the Ticket bean might look:

@Relation(roleName = "ConcertgoerHasTicket", 
    targetEjb = "Concertgoer", 
    multiplicity = Relation.Multiplicity.ONE, 
    name = "Concertgoer-Ticket")
abstract public class Ticket
    extends GenericEntityBean
    implements EntityBean

The Concertgoer EJB will have a CMR field to set and get a reference to a Ticket object. In contrast, there is no reference from the Ticket to the Concertgoer, meaning that there is no direct way to find out if a particular ticket has been assigned to a concertgoer or not and if it has, who the concertgoer is. (To find this out, you would have to run a query on the Concertgoer EJBs and check each referenced ticket.)

In this particular example, Ticket objects are probably created independently of Concertgoer objects, and the CMR set method is used to associate the Concertgoer with the Ticket. Also, when the concertgoer returns the ticket (and removes herself from the ticket counter database), the Ticket object may not be deleted because it can be resold. When the one-to-one unidirectional relationship is more dependent, as between a Customer and his Address, the Customer EJB may have an setAddress business method, which creates a new Address object first, and then uses the CMR set method to set the reference, as is shown in the following code snippet:

   public void setAddress(String street, String apt, String city, String state, String zip) throws CreateException
   {
       Address currentAddress = this.getAddress( );
       if (currentAddress == null) {
           // Customer's current address not known.	
           newAddress = addressHome.create(street, apt, city, state, zip);
           setAddress(newAddress);
       } 
       else {
           // Update customer's current address. 
           currentAddress.setStreet(street);
           currentAddress.setApt(apt);
           currentAddress.setCity(city);
           currentAddress.setState(state);
           currentAddress.setZip(zip);
       }
   }

Notice that first the CMR get method is used to get the reference to the current address. If the address is not known, a new address object is created after which the reference is set. If there is already a reference to an address, the address object is updated to reflect the new address.

When a customer is removed from the database, the home address can likely be removed as well. To do so, you can specify a cascade delete for this entity relationship, which automatically removes the home address when the customer is removed. For more information, see the @Relation annotation.

With respect to persistent storage of this relationship, one table will have the foreign key column information; that is, hold the a copy of the primary key of the other EJB. Typically the Concertgoer table will have a "Ticket_Index" foreign-key column holding the primary key value of the address (assuming that the Ticket EJB defines only one primary key field; if there are multiple primary key columns, there are multiple foreign key columns holding these values). It is, however, also possible that the Ticket table holds the primary key value of the Concertgoer. Regardless of the implementation in the database table, the EJB container will ensure that the relationship is correctly represented.

One-to-One, Bidirectional

In a one-to-one bidirectional relationship, object A relates to object B and both reference each other. An example of such a relationship is between a concertgoer and a creditcard, again assuming the perspective of the ticket counter. Each concertgoer has only one credit card (to purchase a ticket), and if a credit card is inadvertently left behind at the ticket counter, it can be returned to the owner.

Here's how the @Relation annotation on the Concertgoer bean might look:

@Relation(roleName = "ConcertgoerHasCreditCard", 
    cmrField = "creditCard", 
    targetEjb = "CreditCard", 
    multiplicity = Relation.Multiplicity.ONE, 
    name = "Concertgoer-CreditCard")
abstract public class Concertgoer
    extends GenericEntityBean
    implements EntityBean

Here's how the @Relation annotation on the CreditCard bean might look:

@Relation(roleName = "CreditCardNamesConcertgoer", 
    cmrField = "concergoer", 
    targetEjb = "Concertgoer", 
    multiplicity = Relation.Multiplicity.ONE, 
    name = "Concertgoer-CreditCard")
abstract public class CreditCard
    extends GenericEntityBean
    implements EntityBean

The Concertgoer EJB will have a CMR field to set and get a reference to a CreditCard object. In addition, the CreditCard object will have a CMR field to set and get a reference to a Concertgoer object. Also, the bidirectionality of this relationship is ensured by the EJB container. That is, when you use the Concertgoer's CMR set method to set a reference to a CreditCard object, the CMR field of the CreditCard object is automatically updated to hold a reference to this Concertgoer. Similarly, when you change or remove a reference in one object, this change is automatically applied to the other object. As far as creating and deleting the object a CMR field references, similar design considerations apply as discussed above for one-to-one unidirectional relationships. With respect to creating a new creditcard for a concertgoer, it is possible that the Concertgoer EJB has a business method setCreditCard, which creates a new creditcard record and then sets the reference, similar to the setAddress method shown above. If on the other hand the CreditCard EJB defines a create method that creates the CreditCard object and sets the reference to the Concertgoer object, the reference must be set in the ejbPostCreate step. An example of this is shown below.

With respect to persistent storage of this relationship, there is again quite some flexibility how this is implemented in the database tables. One of the possibilities is that only the ConcertGoer table has a foreign key column holding the primary key value of a creditcard. There are other possibilities as well. Regardless of the implementation in the database table, the EJB container will ensure that the relationship is correctly represented.

One-to-Many, Unidirectional

In a one-to-many unidirectional relationship, object A relates to many objects B, there are references from object A to all objects B, but not the other way around. An example of such a relationship is between a concertgoer and CDs purchased after the concert. A concertgoer can purchase many CDs, but for a purchased CD, again inadvertently lost and found, it is not possible to trace it back to the concertgoer who made the purchase.

Here's how the @Relation annotation on the Concertgoer bean might look:

@Relation(roleName = "ConcertgoerBoughtCDs", 
    cmrField = "compactDisc", 
    targetEjb = "CompactDisc", 
    multiplicity = Relation.Multiplicity.ONE, 
    name = "Concertgoer-CDs")
abstract public class Concertgoer
    extends GenericEntityBean
    implements EntityBean

Here's how the @Relation annotation on the CompactDisc bean might look:

@Relation(roleName = "CDsBoughtByConcertgoer", 
    targetEjb = "Concertgoer", 
    multiplicity = Relation.Multiplicity.MANY, 
    name = "Concertgoer-CDs")
abstract public class CompactDisc
    extends GenericEntityBean
    implements EntityBean

The Concertgoer EJB will have a CMR field to set and get a Collection/Set of references to CD objects. In contrast, there is no CMR field in the CD object. The choice of java.util.Collection versus java.util.Set depends on whether from a design perspective it makes sense to have a collection with potentially duplicate references to the same object, or to have a set without duplicate references.

In this particular example, Concertgoer objects are probably created independently of CD objects, and a new reference is added to the CMR field uses the Collection/Set's add method, while a reference is deleted without deleting the CD object using the Collection/Set's remove method. When the relationship is more dependent, as between a Band and its Recordings, the Band EJB may have an addRecording business method, which creates a new Recording object first, and then adds it to the collection, as is shown in the following code snippet:

public void addRecording(String recording) throws CreateException
{
    Recording album = recordingHome.create(getBandName(), recording);
    Collection recordings = getRecordings();
    if(album != null) {
        recordings.add(album);
    }
}

Notice that this method first creates the album, then uses the CMR get method to obtain a collection of the current recordings of the band, and then adds the new recording to the collection. Without the last step the recording would be created, but would not be referenced by the band.

When the Band object is deleted from the database, it might or might not make sense to cascade delete its recordings, depending on the real-world scenario you are representing.

With respect to persistent storage of this relationship, the only possible implementation is for the CD table to have a foreign key column holding the primary value of the concertgoer. As you might notice, the model and the actual implementation are reversed; the EJB container again ensures that the relationship is correctly represented.

Note. WebLogic Server at present doesn't support the use of a join table to implement one-to-many relationships.

One-to-Many, Bidirectional

In a one-to-many bidirectional relationship, object A relates to many objects B, there are references from object A to all objects B, and each object B references object A. An example of such a relationship is between a concertgoer and a creditcard, assuming the perspective of the concertgoer. Each concertgoer can have many credit cards, and if a credit card is inadvertently lost, it can be returned to the owner. Notice that this is the second example of a relationship between a concertgoer and creditcard. Above a one-to-one bidirectional relationship was defined, assuming the perspective of the ticket counter instead of the concertgoer.

Note: Realize that one-to-many bidirectional relationships and many-to-one bidirectional relationships are conceptually identical and are therefore listed as one type of relationship.

Here's how the @Relation annotation on the Concertgoer bean might look:

@Relation(roleName = "ConcertgoerHasCreditCards", 
    cmrField = "creditCards", 
    targetEjb = "CreditCard",
    multiplicity = Relation.Multiplicity.ONE, 
    name = "Concertgoer-CreditCards")
abstract public class Concertgoer
    extends GenericEntityBean
    implements EntityBean

Here's how the @Relation annotation on the CreditCard bean might look:

@Relation(roleName = "CreditCardsBelongToConcertgoer", 
    cmrField = "concergoer", 
    targetEjb = "Concertgoer", 
    multiplicity = Relation.Multiplicity.MANY, 
    name = "Concertgoer-CreditCards")
abstract public class CreditCard
    extends GenericEntityBean
    implements EntityBean

The Concertgoer EJB will have a CMR field to set and get a Collection/Set of references to CreditCard objects. The CreditCard object will have a CMR field to set and get a reference to a ConcertGoer object. Again, the bidirectionality of this relationship is ensured by the EJB container. That is, when you set/add the reference to one of the EJBs, the reference is automatically updated for the other EJB. As far as creating and deleting the object a CMR field references, similar design considerations apply as discussed above.

With respect to persistent storage of this relationship, the only possible implementation is for the CreditCard table to have a foreign key column holding the primary value of the concertgoer.

Note. WebLogic at present doesn't support the use of a join table to implement one-to-many relationships.

Many-to-One, Unidirectional

In a many-to-one unidirectional relationship, many objects A relate to one object B, there is a reference from each object A to object B, but not the other way around. An example of such a relationship is between a concert and a venue, assuming the perspective of a concertgoer. There are many different concerts at the same venue but the concertgoer is probably less concerned to know the concerts given the venue. However, if the latter is a business requirement, you will model this as a one-to-many (venue-to-concerts) bidirectional relationship.

Here's how the @Relation annotation on the Venue bean might look:

@Relation(roleName = "VenueHostsConcerts", 
    targetEjb = "Concert",
    multiplicity = Relation.Multiplicity.ONE, 
    name = "Venue-Concerts")
abstract public class Venue
    extends GenericEntityBean
    implements EntityBean

Here's how the @Relation annotation on the Concert bean might look:

@Relation(roleName = "ConcertsOccurAtVenue", 
    cmrField = "venue", 
    targetEjb = "Venue", 
    multiplicity = Relation.Multiplicity.MANY, 
    name = "Venue-Concerts")
abstract public class Concert
    extends GenericEntityBean
    implements EntityBean

The Concert EJB will have a CMR field to set and get a reference to a Venue object. In contrast, the Venue object will not have a CMR field. When a new concert is scheduled, the venue likely needs to be known at this time. In other words, when you create a Concert object, the reference to the Venue object should be set as part of the create procedure, as is shown in the following example:

abstract public class ConcertBean extends GenericEntityBean implements EntityBean
{
   ...

   public Integer ejbCreate(String bandName, Venue theVenue) {
       setBandName(bandName);
       return null;
   }
	
   public void ejbPostCreate(String bandName, Venue theVenue) {
       setVenue(theVenue);
   }

   ...

Notice that ejbCreate sets the name of the performing band, while the reference to the Venue object is set in the corresponding ejbPostCreate method. References must by design always be set in the ejbPostCreate method, because the primary key(s) needed to set the reference may not be available yet until after creation of the object.

Cascade deletions will most likely not make sense for this relationship. That is, removing one concert should not lead to the destruction of the venue, as many other concerts are scheduled for this venue.

With respect to persistent storage of this relationship, the only possible implementation is for the Concert table to have a foreign key column holding the primary value of the venue.

Note. WebLogic at present doesn't support the use of a join table to implement one-to-many relationships.

Many-to-Many, Unidirectional

In a many-to-many unidirectional relationship, object A relates to many objects B, object B relates to many objects A, there are references from each object A to its objects B, but not the other way around. An example of such a relationship is between concertgoers and concerts. A concertgoer will attend many concerts, each concerts will attract many concertgoers, given a concertgoer you might want to know the concerts he/she attended, but given a concert you likely don't want to know the particular concertgoers that were attending it.

Here's how the @Relation annotation on the Concertgoer bean might look:

@Relation(roleName = "ConcertgoerAttendsConcerts", 
    cmrField = "concerts", 
    targetEjb = "Concert",
    multiplicity = Relation.Multiplicity.MANY, 
    name = "Concertgoer-Concerts")
abstract public class Concertgoer
    extends GenericEntityBean
    implements EntityBean

Here's how the @Relation annotation on the Concert bean might look:

@Relation(roleName = "ConcertsHaveManyConcertgoers", 
    targetEjb = "Concertgoer", 
    multiplicity = Relation.Multiplicity.MANY, 
    name = "Concertgoer-Concerts")
abstract public class Concert
    extends GenericEntityBean
    implements EntityBean

The Concertgoers EJB will have a CMR field to set and get a collection/set of references to Concert objects. In contrast, the Concert object will not have a CMR field. As far as manipulating the CMR field, and creating and deleting the objects the CMR field references, similar design considerations apply as discussed above. Cascade deletions typically do not make sense for many-to-many relationships.

With respect to persistent storage of this relationship, a join table is used. Each record in a join table has two foreign-key columns, one holding the primary key value of a concertgoer and the other holding the primary key value of the concert (again assuming that both EJBs are defined to have one unique primary key field).

Many-to-Many, Bidirectional

In a many-to-many bidirectional relationship, object A relates to many objects B, object B relates to many objects A, there are references from each object A to its objects B as well as references from each object B to its objects A. An example of such a relationship is between a passenger and a flight. A passenger can take multiple flights, a flight is typically booked by multiple passengers, given a passenger you want to know the flights, and for a flight you want to know exactly which passengers should be on the airplane.

Here's how the @Relation annotation on the Passenger bean might look:

@Relation(roleName = "PassengersTakeFlights", 
    cmrField = "flights", 
    targetEjb = "Flight",
    multiplicity = Relation.Multiplicity.MANY, 
    name = "Paesengers-Flights")
abstract public class Passenger
    extends GenericEntityBean
    implements EntityBean

Here's how the @Relation annotation on the Flight bean might look:

@Relation(roleName = "FlightsHaveManyPassengers", 
    cmrField = "passengers", 
    targetEjb = "Passenger", 
    multiplicity = Relation.Multiplicity.MANY, 
    name = "Passengers-Flights")
abstract public class Flight
    extends GenericEntityBean
    implements EntityBean

The Passenger EJB will have a CMR field to set and get a collection/set of references to Flight objects. The Flight EJB will have a CMR field to set and get a collection/set of references to Passenger objects. As far as manipulating the CMR field, and creating and deleting the objects the CMR field references, similar design considerations apply as discussed above. In this particular example it is possible that a passenger books a flight for several passengers at the same time. You can use the Collection/Set's addAll method to add multiple references. Also notice that bidirectionality is again assured by the EJB container, and that cascade deletions typically do not make sense for many-to-many relationships.

With respect to persistent storage of this relationship, a join table is used. Each record in a join table has two foreign-key columns, one holding the primary key value of a concertgoer and the other holding the primary key value of the concert (again assuming that both EJBs are defined to have one unique primary key field).

Related Topics

@Relation Annotation

 

Skip navigation bar   Back to Top