EJB 3会话Bean设计用于简单的CRUD操作

7
我正在编写一个应用程序,其唯一目的是在数据库中维护记录的CRUD操作。某些表/实体之间存在关系。大多数创建会话Bean的示例都涉及与我没有的许多实体交互的复杂业务逻辑/操作。
由于我的应用程序非常基础,因此哪种会话Bean设计最佳呢?
我考虑每个实体一个会话Bean,其中定义了CRUD方法。然后我考虑将所有这些会话Bean合并为单个会话Bean。然后我发现了这篇博客文章,它很有趣,但我必须承认我不理解其中的所有内容(什么是ServiceFacade?)。
我倾向于使用会话Bean /实体类,但希望听取更有经验的意见。
谢谢。
糟糕,这里是博客链接:http://www.adam-bien.com/roller/abien/entry/generic_crud_service_aka_dao
1个回答

11

不确定您在谈论哪篇博客文章 :) 但在您的特定情况1下,我可能会使用一个单一的会话bean来实现类似于以下接口的接口:

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);
}

以下是豆子的内容:
@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();
    }
}

参见

1 大多数应用程序不应直接向客户端公开原始CRUD,而是将其隐藏在实现业务规则并封装对域存储(EntityManager)访问的服务后面。


抱歉忘记发布博客链接,我已经编辑/添加了它。 它与您的解决方案非常相似,但指出“接口实现实际上是一个服务,必须始终在ServiceFacade后面执行”,这一点我还没有弄清楚。 - sdoca
我花了一些时间才理解泛型类(仍在努力掌握泛型)。但是,我弄清楚了它们的意义/作用。谢谢! - sdoca
你之前的实现是否按照你所说的“将CRUD操作封装在实现业务规则的服务后面,并封装对EntityManager的访问”?看起来你没有封装对EntityManager的访问。你应该如何修改代码以封装EntityManager的访问呢?还有一个问题,当我尝试从我的托管Bean中访问EJB时,我必须使用@EJB private GenericCrudService myEJB,而不是@EJB private GenericCrudServiceBean myEJB。我认为后者更有意义,因为GenericCrudService只是一个接口,而GenericCrudServiceBean是一个无状态Bean。 - Thang Pham
我对我的解决方案还有几个问题,我在这里发布了一个新的问题,请帮忙:https://dev59.com/0lbTa4cB1Zd3GeqP8Cd6 - Thang Pham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接