EJB 3 Session Bean Design for Simple CRUD
Asked Answered
C

1

7

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

Citizenship answered 31/5, 2010 at 22:35 Comment(0)
C
11

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).

Cheese answered 31/5, 2010 at 23:17 Comment(4)
Sorry forgot to post the link to the blog, I have edited/added it. It is very similar to your solution, but states that "The interface-implementation is actually a Service, which always has to be executed behind a ServiceFacade" which I haven't figured out yet.Citizenship
It took me awhile to understand the generic classes (still getting a grasp on generics). But, I figured out what theymean/do. Thanks!Citizenship
Did your implementation above did what u said,shield CRUD behinds services implementing business rules and encapsulate access to EntityManager. It seems that you did not encapsulate access to EntityManager. How should you fix the above code to encapsulate EntityManager. One more question, when I try to access the EJB from my Managed Bean, I have to do @EJB private GenericCrudService myEJB, instead of @EJB private GenericCrudServiceBean myEJB. I thought the latter would make more sense because GenericCrudService is just and interface, GenericCrudServiceBean is a stateless beanBreastbeating
I have couple more question about my solution, I post a new question here, please help: #5641810Breastbeating

© 2022 - 2024 — McMap. All rights reserved.