Entity Relationships (Enterprise JavaBeans 3.1)

 

This topic retools our employee registry a bit further by discussing the relationships between entities.

In order to model real-world business concepts, entity beans must be capable of forming relationships. For instance, an employee may have an address; we’d like to form an association between the two in our database model. The address could be queried and cached like any other entity, yet a close relationship would be forged with the Employee entity. Entity beans can also have one-to-many, many-to-one, and many-to-many relationships. For example, the Employee entity may have many phone numbers, but each phone number belongs to only one employee (a one-to-many relationship). Similarly, an employee may belong to many teams within his or her organization, and teams may have any number of employees (a many-to-many relationship).

The Seven Relationship Types

Seven types of relationships can exist between entity beans. There are four types of cardinality: one-to-one, one-to-many, many-to-one, and many-to-many. In addition, each relationship can be either unidirectional or bidirectional. These options seem to yield eight possibilities, but if you think about it, you’ll realize that one-to-many and many-to-one bidirectional relationships are actually the same thing. Thus, there are only seven distinct relationship types. To understand relationships, it helps to think about some simple examples:

One-to-one unidirectional

The relationship between an employee and an address. You clearly want to be able to look up an employee’s address, but you probably don’t care about looking up an address’s employee. One-to-one bidirectional

The relationship between an employee and a computer. Given an employee, we’ll need to be able to look up the computer ID for tracing purposes. Assuming thecomputer is in the tech department for servicing, it’s also helpful to locate the employee when all work is completed. One-to-many unidirectional

The relationship between an employee and a phone number. An employee can have many phone numbers (business, home, cell, etc.). You might need to look up an employee’s phone number, but you probably wouldn’t use one of those numbers to look up the employee.

One-to-many bidirectional

The relationship between an employee (manager) and direct reports. Given a manager, we’d like to know who’s working under him or her. Similarly, we’d like to be able to find the manager for a given employee. (Note that a many-to-one bidirectional relationship is just another perspective on the same concept.) Many-to-one unidirectional

The relationship between a customer and his or her primary employee contact. Given a customer, we’d like to know who’s in charge of handling the account. It might be less useful to look up all the accounts a specific employee is fronting, although if you want this capability you can implement a many-to-one bidirectional relationship.

Many-to-many unidirectional

The relationship between employees and tasks to be completed. Each task may be assigned to a number of employees, and employees may be responsible for many tasks. For now we’ll assume that given a task we need to find its related employees, but not the other way around. (If you think you need to do so, implement it as a bidirectional relationship.) Many-to-many bidirectional

The relationship between an employee and the teams to which he or she belongs. Teams may also have many employees, and we’d like to do lookups in both directions.

Note that these relations represent the navigability of your domain model. Using JPA QL or the Criteria API, you’ll be able to return even an unmapped association (for example, return the tasks for a given employee even if the association has been mapped as many-to-one unidirectional). Once again, the associations defined in the metadata represent the domain object navigation only.

In this topic, we discuss how to specify relationships by applying annotations to your related entity beans. We also discuss several different common database schemas, and you will learn how to map them to your annotated relationships.

One-to-One Unidirectional Relationship

An example of a one-to-one unidirectional relationship is one between our Employee entity and an Address. In this instance, each employee has exactly one address, and each address has exactly one employee. Which bean references which determines the direction of navigation. While the Employee has a reference to the Address, the Address doesn’t reference the Employee. The relationship is therefore unidirectional; you can only go from the employee to the address, not the other way around through object navigation. In other words, an Address entity has no idea who owns it. Figure 11-1 shows this relationship.

One-to-one unidirectional relationship

Figure 11-1. One-to-one unidirectional relationship

Relational database schema

One-to-one unidirectional relationships normally use a fairly typical relational database schema in which one table contains a foreign key (pointer) to another table. In this case, the Employee table contains a foreign key to the Address table, but the Address table doesn’t contain a foreign key to the Employee table. This allows records in the Address table to be shared by other tables, a scenario explored in “Many-to-Many Unidirectional Relationship” on page 187.

Programming model

In unidirectional relationships (navigated only one way), one of the entity beans defines a property that lets it get or set the other bean in the relationship. Thus, inside the Employee class, you can call the getAddress()/setAddress() methods to access the Address entity, but there are no methods inside the Address class to access the Employee. Let’s look at how we would mark up the Employee bean class to implement this one-to-one relationship to Address:

tmp95247_thumb

A one-to-one relationship is specified using the @javax.persistence.OneToOne annotation and is mapped with the @javax.persistence.JoinColumn annotation. Let’s first look at the @JoinColumn annotation:

tmp95248_thumb

The @JoinColumn annotation is analogous to the @Column annotation. It defines the column in the Employee’s table that references the primary key of the Address table in the schema. If you are joining on something other than the primary-key column of the Address table, then you must use the referencedColumnName() attribute. This referencedColumnName() must be unique, since this is a one-to-one relationship.

If you need to map a one-to-one relationship in which the related entity has a composite primary key, use the @JoinColumns annotation to define multiple foreign-key columns:

tmp95249_thumb

Now let’s learn about the @OneToOne annotation:

tmp95250_thumb

The targetEntity() attribute represents the entity class you have a relationship to. Usually, you do not have to initialize this attribute, as the persistence provider can figure out the relationship you are setting up from the property’s type.

The fetch() attribute works the same as we described. It allows you to specify whether you want the association to be lazily or eagerly loaded. We’ll show you how you can eagerly fetch a relationship with JPA QL or the Criteria API, even when you have marked the FetchType as LAZY.

The optional() attribute specifies whether this relationship can be null. If this is set to false, then a non-null relationship must exist between the two entities.

The cascade() attribute is a bit complicated. We’ll discuss it later in this topic, as all relationship types have this attribute.

The mappedBy() attribute is for bidirectional relationships and is discussed in the next section.

The orphanRemoval() attribute is new to JPA 2.0, and defines whether removing the relationship should also result in a removal of the referred entity.

Primary-key join columns

Sometimes the primary keys of the two related entities are used instead of a specific join column. In this case, the primary keys of the related entities are identical, and there is no need for a specific join column.

In this mapping scenario, you are required to use an alternative annotation to describe the mapping—@javax.persistence.PrimaryKeyJoinColumn:

tmp95251_thumb

The name() attribute refers to the primary-key column name of the entity the annotation is applied to. Unless your entity has a composite primary key, you can leave this blank and the persistence provider will figure it out.

The referencedColumnName() is the column to join to on the related entity. If this is left blank, it is assumed that the related entity’s primary key will be used.

The columnDefinition() is used when the persistence provider is generating schema, and its value will specify the SQL type of the referencedColumnName().

If the primary-key join in question is of a composite nature, then the @javax.persistence.PrimaryKeyJoinColumns annotation is available to you:

tmp95252_thumb

So, we could use this annotation to map the Employee/Address entities’ one-to-one relationship:

tmp95253_thumb

Since we’re joining on the primary keys of the Employee and Address entities and they are not composite keys, we can simply annotate the address property of Employee with the defaulted @PrimaryKeyJoinColumn annotation.

Default relationship mapping

If your persistence provider supports auto schema generation, you do not need to specify metadata such as @JoinColumn or @PrimaryKeyJoinColumn. Auto schema generation is great when you are doing fast prototypes: @OneToOneprivate Address address;

When you do not specify any database mapping for a unidirectional one-to-one relationship, the persistence provider will generate the necessary foreign-key mappings for you. In our employee/address relationship example, the following tables would be generated:

tmp95254_thumb

For unidirectional one-to-one relationships, the default mapping creates a foreign-key column named from a combination of the property you are mapping followed by an _ (underscore) character concatenated with the primary-key column name of the referenced table.

One-to-One Bidirectional Relationship

We can expand our Employee entity to include a reference to a Computer entity, which models the associate’s company-provided computer. The employee will maintain a reference to his or her computer, and the computer will maintain a reference back to the employee. This makes good sense, since we may need to know the owner of a computer.


The Computer has a corresponding COMPUTER table, which will contain a pointer to its Employee owner:

tmp971_thumb_thumb

One-to-one bidirectional relationships may model relational database schemas in the same way as our one-to-one unidirectional relationship, in which one of the tables holds a foreign key that references the other. Remember that in a relational database model, there is no such notion of directionality, so the same database schema will be used for both unidirectional and bidirectional object relationships.

To model the relationship between the Employee and Computer entities, we need to declare a relationship property named owner in the Computer bean class:

tmp972_thumb_thumb

Similarly, the Employee class will have a reference to the Computer:

tmp973_thumb_thumb

The mappedBy() attribute is new here. This attribute sets up the bidirectional relationship and tells the persistence manager that the information for mapping this relationship to our tables is specified in the Computer bean class, specifically to the owner property of Computer.

Here is an example for setting up a bidirectional relationship:

tmp974_thumb_thumb

We have the cascade() attribute set to empty, so we must perform the association after each object is persisted and therefore managed. When we discuss cascading operations, you will see that there are ways to persist unmanaged objects as part of an association automatically.

There are some peculiarities with bidirectional relationships. With all bidirectional relationship types, including one-to-one, there is always the concept of an owning side of the relationship. Although a setOwner() method is available in the Computer bean class, it will not cause a change in the persistent relationship if we set it. When we marked the @OneToOne relationship in the Employee bean class with the mappedBy() attribute, this designated the Employee entity as the inverse side of the relationship. This means that the Computer entity is the owning side of the relationship.

Always wire both sides of a bidirectional relationship when modifying relationships. Entities are like any other Java object that has an association to another object. You have to set the values of both sides of the relationship in memory for the relationship to be updated.

If the employee broke his computer, you would have to set the relationship to null on both sides and then remove the Computer entity from the database.

One-to-Many Unidirectional Relationship

Entity beans can also maintain relationships with multiplicity. This means one entity bean can aggregate or contain many other entity beans. For example, an employee may have relationships with many phones, each of which represents a phone number. This is very different from simple one-to-one relationships—or, for that matter, from multiple one-to-one relationships with the same type of bean. One-to-many and many-to-many relationships require the developer to work with a collection of references instead of a single reference when accessing the relationship field.

Relational database schema

To illustrate a one-to-many unidirectional relationship, we will use a new entity bean, the Phone, for which we must define a table, the PHONE table:

tmp975_thumb_thumb

Likewise, we can introduce a link from Employee to obtain a collection of Phones:

tmp976_thumb2

tmp977_thumb_thumb

One-to-many unidirectional relationships between the EMPLOYEE and PHONE tables could be implemented in a variety of ways. For this example, we have chosen to introduce a new table, a join table, to map phones to employees:

Our database schema illustrates that the structure and relationships of the actual database can differ from the relationships as defined in the programming model. In this case, the relationship in the object model is inferred from the reference Employee has to a Collection of Phones, but the database contains a join table. When you are dealing with legacy databases (i.e., databases that were established before the EJB application), it’s important to have the mapping options JPA affords so that the object model is not dictated by the schema.

Programming model

You declare one-to-many relationships using the @javax.persistence.OneToMany annotation:

tmp978_thumb_thumb

The attribute definitions are pretty much the same as those for the @OneToOne annotation.

In the programming model, we represent multiplicity by defining a relationship property that can point to many entity beans and annotating it with @OneToMany. To hold this type of data, we’ll employ some data structures from the java.util package: Collection, List, Map, and Set. The Collection maintains a homogeneous group of entity object references, which means that it contains many references to one kind of entity bean. The Collection type may contain duplicate references to the same entity bean, and the Set type may not.

To illustrate how an entity bean uses a collection-based relationship, let’s look at some code that interacts with the EntityManager:

tmp979_thumb_thumb

Removing the Phone from the Employee’s collection does not remove the Phone from the database. You have to delete the Phone explicitly; otherwise, it will be orphaned. The orphanRemoval attribute of @OneToMany may remove the orphaned phone automatically if set to true.

Many-to-One Unidirectional Relationship

Many-to-one unidirectional relationships result when many entity beans reference a single entity bean, but the referenced entity bean is unaware of the relationship. In our example company, we have a series of Customers who are each assigned to an Employee who is the primary contact for the customer account. An Employee may be the point person for many Customers, but the relationship will be one-way; customers will know who their primary contact is, but Employees will not refer to all of their Customers.

Relational database schema

Here we introduce a CUSTOMER table to model our customers:

tmp9710_thumb_thumb

Programming model

Many-to-one relationships are described with the @javax.persistence.ManyToOne annotation:

// Associate

jaikiranPai.getPhones().add(phonel); jaikiranPai.getPhones().add(phone2);

If you need to remove a Phone from the relationship, you need to remove the Phone from both the collection and the database:

tmp9712_thumb_thumbtmp9711_thumb_thumb

tmp9713_thumb_thumb

The attribute definitions are pretty much the same as those for the @OneToOne annotation.

The programming model is quite simple for our relationship. We add a primaryContact property to our Customer entity bean class and annotate it with the @ManyToOne annotation:

tmp9714_thumb_thumb

The relationship between the Employee and Customer entities is unidirectional, so the Employee bean class doesn’t define any relationship back to the Customer.

All of this should be mundane to you now. The impact of exchanging Employee references between Customer entities works just as we’ve seen with the previous relationship types.

One-to-Many Bidirectional Relationship

One-to-many and many-to-one bidirectional relationships sound like they’re different, but they’re not. A one-to-many bidirectional relationship occurs when one entity bean maintains a collection-based relationship property with another entity bean, and each entity bean referenced in the collection maintains a single reference back to its aggregating bean. For example, in our company an employee has a manager, and likewise a manager has many direct reports. The relationship is a one-to-many bidirectional relationship from the perspective of the manager (an Employee) and a many-to-one bidirectional relationship from the perspective of the report (also an Employee). For fun’s sake, let’s label “reports” in this sense as “peons.” This becomes an interesting exercise as well, because it shows that relationships may exist within a single entity type.

Relational database schema

First, we need to equip our EMPLOYEE table with the support necessary to model the manager/peon relationship:

tmp9715_thumb_thumbtmp9716_thumb_thumb

Now each Employee has a reference to his or her manager. Programming model

Because this is a bidirectional relationship, the manager knows his or her reports, and also his or her own manager. The Employee class may therefore contain:

tmp9717_thumb_thumb

The entire relationship here is contained within the Employee class. As with all bidirectional relationships, the inverse side specifies mappedBy to indicate the property to act as the owning side.

Java Persistence currently requires that the many-to-one side always be the owner. This may seem very confusing, but if you obey the cardinal rule of always wiring both sides of a relationship, then you will have no problems.

Always wire both sides of a bidirectional relationship in your Java code.

Usage

Client usage is as we’ve seen before:

tmp9718_thumb_thumbtmp9719_thumb2

Many-to-Many Bidirectional Relationship

Many-to-many bidirectional relationships occur when many beans maintain a collection-based relationship property with another bean, and each bean referenced in the collection maintains a collection-based relationship property back to the aggregating beans. For example, in our example company every Employee may belong to many Teams, and each Team may be composed of many Employees.

Relational database schema

The EMPLOYEE and TEAM tables may be fairly simple, and neither will have a direct reference to the other:

tmp9720_thumb_thumb

Again, we use a join table to establish a many-to-many bidirectional relationship, and we’ll call this the TEAM_EMPLOYEE table. Here we maintain two foreign key columns— one for the EMPLOYEE table and another for the TEAM table:

tmp9721_thumb_thumbtmp9722_thumb_thumb

Programming model

Many-to-many relationships are logically defined using the @javax.persistence.Many ToMany annotation:

tmp9723_thumb_thumb

To model the many-to-many bidirectional relationship between the Employee and Team entities, we need to include collection-based relationship properties in both bean classes:

tmp9724_thumb1_thumb

The relationship is declared as a java.util.Collection. We could also use a Set type, which would contain only unique Teams and no duplicates. The effectiveness of the Set collection type depends largely on referential-integrity constraints established in the underlying database.

As with all bidirectional relationships, there has to be an owning side. In this case, it is the Team entity. Since the Team owns the relationship, its bean class may have the @JoinTable mapping, though in our example we can accept the defaults. The joinColumns() attribute could identify the foreign-key column in the TEAM_EMPLOYEE table that references the TEAM table, whereas the inverseJoinColumns() attribute could identify the foreign key that references the EMPLOYEE table.

Like with @OneToMany relationships, if you are using your persistence provider’s auto schema generation facilities, you do not need to specify a @JoinTable mapping. The Java Persistence specification has a default mapping for @ManyToMany relationships and will create the join table for you.

As with one-to-many bidirectional relationships, the mappedBy() attribute identifies the property on the Team bean class that defines the relationship. This also identifies the Employee entity as the inverse side of the relationship.

As far as modifying and interacting with the relationship properties, the same ownership rules apply as we saw in the one-to-many bidirectional example:

tmp9725_thumb1_thumb1

Many-to-Many Unidirectional Relationship

Many-to-many unidirectional relationships occur when many beans maintain a collection-based relationship with another bean, but the bean referenced in the Collection does not maintain a collection-based relationship back to the aggregating beans. In our example, we may assign any number of Tasks to any number of Employees, and Employees may be assigned to any number of Tasks. We’ll maintain a reference from Task to Employee, but not the other way around.

Relational database schema

Our first order of business is to declare a TASK table:

tmp9726_thumb1_thumb

This many-to-many unidirectional relationship looks a lot like the join table mapping for the many-to-many bidirectional relationship discussed earlier. The big difference is that the object model will maintain a reference only in one direction.

Programming model

To model this relationship, we need to add a collection-based relationship field for Employee beans to the Task:

tmp9727_thumb_thumbtmp9728_thumb_thumb

Because the relationship is unidirectional, there are no owning or inverse sides, and we may omit the mappedBy attribute of @ManyToMany.

Usage is similar to what we’ve already seen:

tmp9729_thumb1_thumb

Mapping Collection-Based Relationships

The one-to-many and many-to-many examples we’ve seen so far have used the java.util.Collection and java.util.Set types. The Java Persistence specification also allows you to represent a relationship with a java.util.List or a java.util.Map.

Ordered List-Based Relationship

The java.util.List interface can express collection-based relationships. You do not need any special metadata if you want to use a List rather than a Set or Collection type. (In this case, the List actually gives you a bag semantic, an unordered collection that allows duplicates). A List type can give you the additional ability to order the returned relationship based on a specific set of criteria. This requires the additional metadata provided by the @javax.persistence.OrderBy annotation:

tmp9730_thumb_thumbtmp9731_thumb2

The value() attribute allows you to declare partial JPA QL that specifies how you want the relationship to be ordered when it is fetched from the database. If the value() attribute is left empty, the List is sorted in ascending order based on the value of the primary key.

Let’s take the Employee/Team relationship, which is a many-to-many bidirectional relationship, and have the teams attribute of Employee return a List that is sorted alphabetically by the Team entity’s name:

tmp9732_thumb_thumb

“name ASC” tells the persistence provider to sort the Team’s name in ascending order. You can use ASC for ascending order and DESC for descending order. You can also specify additional restrictions, such as @OrderBy(‘ name asc, otherattribute asc”). In this case, the list will be ordered by lastname, and for duplicate names, it will be ordered by the otherattribute.

Map-Based Relationship

The java.util.Map interface can be used to express collection-based relationships. In this case, the persistence provider creates a map, with the key being a specific property of the related entity and the value being the entity itself. If you use a java.util.Map, you must use the @javax.persistence.MapKey annotation:

tmp9733_thumb_thumb

The name() attribute is the name of the persistent property that you want to represent the key field of the map object. If you leave this blank, it is assumed you are using the primary key of the related entity as the key of the map.

For an example, let’s use a map to represent the one-to-many unidirectional Employee/ Phone relationship discussed earlier in this topic:

tmp9734_thumb_thumbtmp9735_thumb_thumb

In this example, the phones property of Employee will return a java.util.Map where the key is the number property of the Phone entity and the value is, of course, the Phone entity itself. There is no extra column to keep the map key, since the map key is borrowed from the Phone entity.

Detached Entities and FetchType

We discussed how managed entity instances become detached from a persistence context when the persistence context ends. Since these entity instances are no longer managed by any persistence context, they may have uninitialized properties or relationships. If you are returning these detached entities to your clients and basically using them as data transfer objects between the client and server, you need to fully understand the effects of accessing any uninitialized relationships.

When an entity instance becomes detached, its state might not be fully initialized, because some of its persistent properties or relationships may be marked as lazily loaded in the mapping metadata. Each relationship annotation has a fetch() attribute that specifies whether the relationship property is loaded when the entity is queried. If the fetch() attribute is set to FetchType.LAZY, then the relationship is not initialized until it is traversed in your code:

tmp9736_thumb_thumb

Invoking the size() method of the phones collection causes the relationship to be loaded from the database. It is important to note that this lazy initialization does not happen unless the entity bean is being managed by a persistence context. If the entity bean is detached, the specification is not clear on what actions the persistence provider should perform when accessing an unloaded relationship of a detached entity. Most persistence providers throw some kind of lazy instantiation exception when you call the accessor of the relationship or when you try to invoke an operation on the relationship of a detached entity:

tmp9737_thumb_thumb

In this code, the application has received an instance of a detached Employee entity and attempts to access the phones relationship. If the fetch() attribute of this relationship is LAZY, most vendor implementations will throw a vendor-specific exception. This lazy initialization problem can be overcome in two ways. The obvious way is just to navigate the needed relationships while the entity instance is still managed by a persistence context. The second way is to perform the fetch eagerly when you query the entity.You will see that the JPA QL query language has a FETCH JOIN operation that allows you to preinitialize selected relationships when you invoke a query.

How is the persistence provider able to throw an exception when accessing the relationship when the Employee class is a plain Java class? Although not defined in the specification, the vendor has a few ways to implement this. One is through bytecode manipulation of the Employee class. In Java EE, the application server is required to provide hooks for bytecode manipulation for persistence providers. In Java SE, the persistence provider may require an additional post-compilation step on your code base. Another way for vendors to implement this is to create a proxy class that inherits from Employee and that reimplements all the accessor methods to add lazy initialization checking. For collection-based relationships, the persistence provider can just provide its own implementation of the collection and do the lazy check there. Whatever the implementation, make a note to discover what your persistence provider will do in the detached lazy initialization scenario so that your code can take appropriate measures to handle this exception.

Cascading

There is one annotation attribute that we have ignored so far: the cascade() attribute of the @OneToOne, @OneToMany, @ManyToOne, and @ManyToMany relationship annotations. This section discusses in detail the behavior that is applied when using the cascade() attribute.

When you perform an entity manager operation on an entity bean instance, you can automatically have the same operation performed on any relationship properties the entity may have. This is called cascading. For example, if you are persisting a new Employee entity with a new address and phone number, all you have to do is wire the object, and the entity manager can automatically create the employee and its related entities, all in one persist() method call:

tmp9738_thumb_thumb

With the Java Persistence specification, cascading can be applied to a variety of entity manager operations, including persist(), merge(), remove(), and refresh(). This

The ALL value represents all of the cascade operations. The remaining values represent individual cascade operations. The cascade() attribute is an array of the cascade operations you want applied to your related entities.

PERSIST

PERSIST has to deal with the creation of entities within the database. If we had a CascadeType of PERSIST on the Employee side of our one-to-one relationship, you would not have to persist your created Address as well. It would be created for you. The persistence provider also will execute the appropriate SQL INSERT statements in the appropriate order for you.

If you did not have a cascade policy of PERSIST, then you would have to call EntityManager.persist() on the address object as well (as we do in the example).

MERGE

MERGE deals with entity synchronization, meaning inserts and, more importantly, updates. These aren’t updates in the traditional sense. If you remember from previous topics, we mentioned that objects could be detached from persistent management and serialized to a remote client, updates could be performed locally on that remote client, the object instance would be sent back to the server, and the changes would be merged back into the database. Merging is about synchronizing the state of a detached object instance back to persistent storage.

Feature is enabled by setting the javax.persistence.CascadeType of the relationship annotation’s cascade() attribute. The CascadeType is defined as a Java enumeration:

tmp9739_thumb_thumb

So, back to what MERGE means! MERGE is similar to PERSIST. If you have a cascade policy of MERGE, then you do not have to call EntityManager.merge() for the contained related entity:

tmp9740_thumb_thumb

In this example, when the employee variable is merged by the entity manager, the entity manager will cascade the merge to the contained address property and the city also will be updated in the database.

Another interesting thing about MERGE is that if you have added any new entities to a relationship that have not been created in the database, they will be persisted and created when the merge() happens:

tmp9741_thumb_thumb

In this example, we allocate a Phone and add it to an Employee’s list of phone numbers. We then call merge() with the employee, and since we have the MERGE CascadeType set on this relationship, the persistence provider will see that it is a new Phone entity and will create it within the database.

Remember that only the graph returned by the merge operation is in managed state, not the one passed as a parameter.

REMOVE

REMOVE is straightforward. In our Employee example, if you delete an Employee entity, its address will be deleted as well:

tmp9742_thumb_thumb

REFRESH

REFRESH is similar to MERGE. Unlike merge, though, this CascadeType only pertains to when EntityManager.refresh() is called. Refreshing doesn’t update the database with changes in the object instance. Instead, it refreshes the object instance’s state from the database. Again, the contained related entities would also be refreshed:

tmp9743_thumb_thumb

So, if changes to the Employee’s address were committed by a different transaction, the address property of the employee variable would be updated with these changes. This is useful in practice when an entity bean has some properties that are generated by the database (by triggers, for example). You can refresh the entity to read those generated properties. In this case, be sure to make those generated properties read-only from a persistence provider perspective, i.e., using the @Column (insertable=false, updatable=false).

ALL

ALL is a combination of all of the previous policies and is used for the purposes of simplicity.

When to Use Cascading

You don’t always want to use cascading for every relationship you have. For instance, you would not want to remove the related Computer or Tasks when removing an Employee entity from the database, because these entities have a life span that is usually longer than the employee. You might not want to cascade merges because you may have fetched stale data from the database or simply not filled the relationship in one particular business operation. For performance reasons, you may also not want to refresh all the relationships an entity has because this would cause more round trips to the database. Be aware how your entities will be used before deciding on the cascade type. If you are unsure of their use, then you should turn off cascading entirely and enable it on a per-case basis. Remember, cascading is simply a convenient tool for reducing the EntityManager API calls. It’s very easy to trigger expensive database calls, which may result in unnecessary multitable joins.

Next post:

Previous post: