A building facade is a false front to a building. Movie sets frequently use facades to give the appearance of an actual building avoiding the cost of a real building. In programming, a facade is an object which provides an interface to another class to make the hidden class easier to use or reduce dependencies among classes.
We will build upon the EntityBeanApplication
application from the previous recipe. We will be adding to the EJB module two new classes to the packt
package: AbstractFacade
and PartsBeanFacade
.
An entity facade is commonly used to hide the entity class. A typical approach is to create a base class encapsulating much of the common functionality of an entity and then extend this class with one providing specific entity support. For example, NetBeans provides a wizard which creates an abstract class possessing a number of useful methods:
getEntityManager
Returns a reference to the EntityManager
for the persistence unit containing the entitycreate
Persists an objectedit
Modifies an existing entry in the databaseremove
Removes an entry from the databasefind
Finds a specific entryfindAll
Returns a List of all entriesfindRange
Returns a List of entries within a specified rangeFirst, create an abstract AbstractFacade
class to support the basic persistence methods listed previously.
package packt; import java.util.List; import javax.persistence.EntityManager; public abstract class AbstractFacade<T> { private Class<T> entityClass; public AbstractFacade(Class<T> entityClass) { this.entityClass = entityClass; } protected abstract EntityManager getEntityManager(); public void create(T entity) { getEntityManager().persist(entity); } public void edit(T entity) { getEntityManager().merge(entity); } public void remove(T entity) { getEntityManager().remove(getEntityManager().merge(entity)); } public T find(Object id) { return getEntityManager().find(entityClass, id); } public List<T> findAll() { javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); cq.select(cq.from(entityClass)); return getEntityManager().createQuery(cq).getResultList(); } public List<T> findRange(int[] range) { javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); cq.select(cq.from(entityClass)); javax.persistence.Query q = getEntityManager().createQuery(cq); q.setMaxResults(range[1] - range[0]); q.setFirstResult(range[0]); return q.getResultList(); } public int count() { javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); javax.persistence.criteria.Root<T> rt = cq.from(entityClass); cq.select(getEntityManager().getCriteriaBuilder().count(rt)); javax.persistence.Query q = getEntityManager().createQuery(cq); return ((Long) q.getSingleResult()).intValue(); } }
Next, create the PartsBeanFacade
class and extend the AbstractFacade
class. To associate this class with an underlying database, use the @PersistenceContext annotation. Notice in its default constructor the PartsBean
class is specified as the entity class to be managed.
Most IDEs provide a means of creating the persistence unit when a facade type class is used. In NetBeans, the wizard used to create an entity provides the option to create a persistence unit in the first step. In the second step, a name is automatically generated but can be changed. Also the persistence provided and data source can be selected. If you are using NetBeans accept the default persistence provider and use jdbc/__default as the data source.
package packt; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @Stateless public class PartsBeanFacade extends AbstractFacade<PartsBean> { @PersistenceContext(unitName = "EntityBeanApplication-ejbPU") private EntityManager em; protected EntityManager getEntityManager() { return em; } public PartsBeanFacade() { super(PartsBean.class); } }
The AbstractFacade
class uses several base EntityManager
methods in support of the entity. Most of these are straightforward mapping of an EntityManager
method to an AbstractFacade
method. However, for the create
method the EntityManager
class method persist
was used and merge
was used for edit
.
The AbstractFacade
class is a generic class capable of being used with a number of different entities. A specific entity is assigned and retrieved using the AbstractFacade's
constructor and its getEntityManager
method. Notice that this method is abstract in AbstractFacade
and was implemented in PartsBeanFacade
.
The AbstractFacade
class's findAll, findRange
, and count
methods do not map directly to an EntityManager
method. Instead, they provide additional capabilities often needed by an entity.
All of these methods use CriteriaQuery
interface methods to return either a list of entities or a count of the number of entities available. This interface is discussed in more detail in Chapter 5,
The PartsBeanFacade
class associated the PartsBean
with a persistence unit using the @PersistenceContext. This annotation injected the entity manager for the persistence unit. It used the attribute, unitName
, to specify the name of the persistence unit.
The PartsBeanFacade
class overrode one method, getEntityManager
. This method returned a reference to the EntityManager
used with the PartsBean
.
52.15.55.18