A more realistic example

In the previous section, we saw a very simple "Hello world" type of example. In this section, we will use a more realistic example. Session beans are frequently used as Data Access Objects (DAOs). Sometimes they are used as a wrapper for JDBC calls, other times they are used to wrap calls to obtain or modify JPA entities. In this section, we will take the latter approach.

The following example illustrates how to implement the DAO design pattern in a session bean. Before looking at the bean implementation, let's look at its corresponding business interface:

package net.ensode.javaeebook; 
 
import javax.ejb.Remote; 
 
@Remote 
public interface CustomerDao 
{ 
  public void saveCustomer(Customer customer); 
 
  public Customer getCustomer(Long customerId); 
 
  public void deleteCustomer(Customer customer); 
} 

As we can see, this is a remote interface implementing three methods; the saveCustomer() method saves customer data to the database, the getCustomer() method obtains data for a customer from the database, and the deleteCustomer() method deletes customer data from the database. All of these methods take an instance of the Customer entity we developed in Chapter 3, Object Relational Mapping with JPA as a parameter.

Let's now take a look at the session bean implementing the preceding business interface. As we are about to see, there are some differences between the way JPA code is implemented in a session bean and in a plain old Java object:

package net.ensode.javaeebook; 
 
import javax.ejb.Stateful; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 
 
@Stateful 
public class CustomerDaoBean implements CustomerDao { 
 
    @PersistenceContext 
    private EntityManager entityManager;     
 
    public void saveCustomer(Customer customer) { 
        if (customer.getCustomerId() == null) { 
            saveNewCustomer(customer); 
        } else { 
            updateCustomer(customer); 
        } 
    } 
 
    private void saveNewCustomer(Customer customer) { 
        entityManager.persist(customer); 
    } 
 
    private void updateCustomer(Customer customer) { 
        entityManager.merge(customer); 
    } 
 
    public Customer getCustomer(Long customerId) { 
        Customer customer; 
 
        customer = entityManager.find(Customer.class, customerId); 
 
        return customer; 
    } 
 
    public void deleteCustomer(Customer customer) { 
        entityManager.remove(customer); 
    } 
} 

The main difference between the preceding session bean and previous JPA examples is that in previous examples, JPA calls were wrapped between calls to UserTransaction.begin() and UserTransaction.commit(). The reason we had to do this is because JPA calls are required to be wrapped in a transaction; if they are not in a transaction, most JPA calls will throw a TransactionRequiredException. The reason we don't have to explicitly wrap JPA calls in a transaction like in previous examples is because session bean methods are implicitly transactional, there is nothing we need to do to make them that way. This default behavior is what is known as container-managed transactions. Container-managed transactions are discussed in detail later in this chapter.

As mentioned in Chapter 3, Object Relational Mapping with Java Persistence API, when a JPA entity is retrieved in one transaction and updated in a different transaction, the EntityManager.merge() method needs to be invoked to update the data in the database. Invoking EntityManager.persist() in this case will result in a "Cannot persist detached object" exception.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.83.96