使用JPA和CDI的JSF应用程序后端架构

时间:2014-11-14 07:22:22

标签: jsf jpa architecture cdi

我正在使用JPA和CDI处理JSF应用程序;我使用以下后端架构:

  • 控制器(JSF流程的CDI注释)
  • 服务(CDI注释将注入控制器和其他服务)
  • DAO(使用EntityManager处理)

我的问题是,应该如何处理EntityManager和事务? 例如,事务(我不使用EJB或Deltaspike,因此没有可用的声明性事务)应该由服务层管理(我是对的吗?),但每个数据相关的其他操作应该由DAO处理。那么应该在哪里注入EntityManager?

另外,EntityManager应该是请求(或会话或方法)作用域吗?

谢谢, krisy

1 个答案:

答案 0 :(得分:1)

我会使用服务层来管理业务逻辑和数据访问层来管理对象关系模型。由于上述原因,实体经理和交易应该是DAO的一部分。保持交易尽可能短是很重要的。

决定选择哪种类型的范围并不明显,因为它取决于bean /应用程序的性质。使用示例用法this演示文稿,幻灯片#15:

  • @RequestScoped:DTO / Models,JSF支持bean
  • @ConversationScoped:多步工作流程,购物车
  • @SessionScoped:用户登录凭据
  • @ApplicationScoped:整个应用分享的数据,缓存

正如您所看到的,给定bean的范围和相关的实体管理器特定于它所关注的问题。如果给定的bean是请求作用域,则在同一HTTP会话中为单个HTTP请求保留其状态。对于会话作用域 bean,状态通过HTTP会话维护。示例方法可能看起来像以下(伪代码):

@SessionScoped // conversation, application scoped as well
public class ServiceImpl implements Service {
    @Inject
    private Dao dao;

    public void createSomething(SomeDto dto) {
        // dto -> entity transformation
        dao.create(entity);
    }

    public SomeDto getSomething(int id) {
        SomeEntity entity = em.findById(id);
        // entity -> dto transformation
        return dto;
    }
}
@RequestScoped
@Transactional
public class DaoImpl implements Dao {
    @Inject
    private EntityManager em; //creating em is cheap

    // TxType.REQUIRED by default
    public void create(SomeEntity entity) { 
        em.persist(entity);
    }

    @Transactional(TxType.NOT_SUPPORTED)
    public SomeEntity findById(int id) {
        return em.find(SomeEntity.class, id);
    }   
}