Search code examples
javajakarta-eeejb-3.0ejbsession-bean

EJB 3 Session Bean Design for Simple CRUD


I am writing an application that's sole purpose in life is to do CRUD operations for maintaining records in database. There are relationships between some of the tables/entities. Most examples I've seen for creating session beans deals with complex business logic/operations that interact with many entities which I don't have.

Since my application is so very basic, what would be the best design for the session bean(s)?

I was thinking of having one session bean per entity which had CRUD the methods defined. Then I thought of combining all of those session beans into a single session bean. And then I found this blog entry which is intriguing, but I must admit I don't understand all of it (what is a ServiceFacade?).

I'm leaning towards session bean/entity class, but would like to hear more experienced opinions.

Thanks.


Oops, here's the blog link: http://www.adam-bien.com/roller/abien/entry/generic_crud_service_aka_dao


Solution

  • Not sure what blog entry you're talking about :) But in your particular situation1, I'd probably use a single session bean implementing an interface similar to:

    public interface GenericCrudService {
        public <T> T create(T t);
        public <T> T find(Class<T> type, Object id);
        public <T> void delete(T t);
        public <T> T update(T t);
        public List findWithNamedQuery(String queryName);
        public List findWithNamedQuery(String queryName, int resultLimit);
        public List findWithNamedQuery(String namedQueryName, 
                                       Map<String, Object> parameters);
        public List findWithNamedQuery(String namedQueryName, 
                                       Map<String, Object> parameters,
                                       int resultLimit);
        public <T> List<T> findWithNativeQuery(String sql, Class<T> type);
    }
    

    And the bean would be as follow:

    @Stateless
    @Remote(GenericCrudService.class)
    @TransactionAttribute(TransactionAttributeType.MANDATORY)
    public class GenericCrudServiceBean implements GenericCrudService {
        @PersistenceContext
        private EntityManager em;
    
        @Override
        public <T> T create(T t) {
            em.persist(t);
            return t;
        }
    
        @Override
        public <T> T find(Class<T> type, Object id) {
            return em.find(type, id);
        }
    
        @Override
        public <T> void delete(T t) {
            t = em.merge(t);
            em.remove(t);
        }
    
        @Override
        public <T> T update(T t) {
            return em.merge(t);
        }
    
        @Override
        public List findWithNamedQuery(String queryName) {
            return em.createNamedQuery(queryName).getResultList();
        }
    
        @Override
        public List findWithNamedQuery(String queryName, int resultLimit) {
            return em.createNamedQuery(queryName).setMaxResults(resultLimit)
                    .getResultList();
        }
    
        @Override
        public List findWithNamedQuery(String namedQueryName,
                                       Map<String, Object> parameters) {
            return findWithNamedQuery(namedQueryName, parameters, 0);          
        }
    
        @Override
        public List findWithNamedQuery(String namedQueryName,
                                       Map<String, Object> parameters,
                                       int resultLimit) {
            Query query = this.em.createNamedQuery(namedQueryName);
            if(resultLimit > 0) {
                query.setMaxResults(resultLimit);            
            }
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                query.setParameter(entry.getKey(), entry.getValue());
            }
            return query.getResultList();
        }
    
        @Override
        @SuppressWarnings("unchecked")
        public <T>  List<T> findWithNativeQuery(String sql, Class<T> type) {
            return em.createNativeQuery(sql, type).getResultList();
        }
    }
    

    See also

    1 Most application shouldn't expose raw CRUD directly to clients but shield CRUD behind services implementing business rules and encapsulating access to Domain Stores (the EntityManager).