Extending the HCL Commerce object model with session beans

HCL Commerce has implemented core commerce objects using JPA entities.

There are, however, some situations in which it is recommended to use a session bean JDBC helper. These situations include the following:

  • A case where a query returns a large result set. This is referred to as the large result set case.
  • A case where a query retrieves data from several tables. This is referred to as the aggregate entity case.
  • A case where an SQL statement performs a database intensive operation. This is referred to as the arbitrary SQL case.

More details are provided in the following sections.

Note that if the session bean is being used as a JDBC wrapper to retrieve information from the database, it becomes more difficult to implement resource-level access control. When a session bean is used in this manner, the developer of the session bean must add the appropriate " where" clauses to the " select" statement in order to prevent unauthorized users from accessing resources.

Large result set case

There are cases where a query returns a large result set and the data retrieved are mainly for read or display purpose. In this case, it is better to use a stateless session bean and within that session bean, create a finder method that performs the same functions as a finder method in an entity bean. That is, the finder method in the stateless session bean should do the following:

  • Perform an SQL select statement
  • For each row that is fetched, instantiate an access bean
  • For each column retrieved, set the corresponding attributes in the access bean

When the access bean is returned, the command is unaware of whether the access bean was returned by a finder method in a session bean or from a finder method in an entity bean. As a result, using a finder method in a session bean does not cause any change to the programming model. Only the calling command is aware of whether it is invoking a finder method in a session bean or in an entity bean. It is transparent to all other parts of the programming model.

Aggregate entity case

In this case, one view combines parts of several objects and a single display page is populated with pieces of information that come from several database tables. For example, consider the concept of "My Account". This may consist of information from table of customer information (for example, the customer name, age and customer ID) and information from an address table (for example, an address made up of a street and city).

It is possible to construct a simple SQL statement to retrieve all of the information from the various tables by performing an SQL join. This can be referred to as performing a "deep fetch". The following is an example of an SQL select statement for the "My Account" example, where the CUSTOMER table is T1 and the ADDRESS table is T2:


select T1.NAME, T1.AGE, T2.STREET, T2.CITY
  from CUSTOMER T1, ADDRESS T2
  where (T1.ID=? and T1.ID=T2.ID)

In order to perform a deep fetch, it is recommended that you use a session bean. In that session bean, create a finder method to retrieve the required information. The finder method should do the following:

  • Perform an SQL select statement for the deep fetch
  • Instantiate an access bean for each row in the main table as well as for each associated object
  • For each column fetched and for each associated object fetched, set the corresponding attribute in the access bean

Note that an access bean does not cache a getter method that returns another access bean. In this case, you should create a simple wrapper class for the access bean using the following pattern:


public class CustomerAccessBeanCopy extends CustomerAccessBean {
   private AddressAccessBean address=null;

   /* The following method overrides the getAddress method in 
      the CustomerAccessBean.
   */
   public AddressAccessBean getAddress() {
      if (address == null)
         address = super.getAddress();
      return address;
      }

    /* The following method sets the address to the copy. */

    public void _setAddress(AddressAccessBean aBean) {
       address = aBean;
      }
} 

Continuing the CUSTOMER and ADDRESS example, the session bean finder method would instantiate a CustomerAccessBean for each row in the CUSTOMER table and an AddressAccessBean for each corresponding row in the ADDRESS table. Then, for each column in the ADDRESS table, it would set the attributes in the AddressAccessBean (street and city); for each column in the CUSTOMER table, it would set the attributes in the CustomerAccessBean (name, age, and address). This is shown in the following diagram.

Diagram showing the flow of information from the AddressAccessBean to the CustomerAccessBean thru the _setAddress method, as detailed in the preceding paragraph.

Arbitrary SQL case

In this case, there is a set of arbitrary SQL statements that perform database-intensive operations. For example, the operation to sum all the rows in a table would be considered a database intensive operation. It is possible that not all of the selected rows correspond to an entity bean in the persistent model.

An example that could result in the creation of an arbitrary SQL statement is a when a customer tries to browse through a very large set of data. For example, if the customer wanted to examine all of the fasteners in an online hardware store, or all of the dresses in an online clothing store. This creates a very large result set, but out of this result set, it is most likely that only a few fields from each row are required. That is, the customer may only initially be presented with a summary showing the item name, picture and price.

In this case, create a session bean helper method. This session bean helper method either performs a read or a write operation. When performing a read operation, it returns a read-only value object that is used for display purposes.

With proper data modeling, the number of cases of arbitrary SQL statements can usually be minimized.