哪个CDI范围应该是JPA存储库的首选

时间:2014-10-07 21:19:02

标签: java java-ee jpa scope cdi

如何为JPA存储库确定适当的CDI范围,如下所示?

@Transactional
public class CategoryRep extends EntityRepository<Integer, Category> {

    private static final long serialVersionUID = 856370976984333182L;

    public List<Category> getAllCategories() {
        // TODO
    }

    public List<Post> getAllPostsOfCategory(Integer categoryId) {
        // TODO
    }

    @Transactional(value = TxType.REQUIRES_NEW, rollbackOn = RuntimeException.class)
    public void createCategory(final String name, final String description)
            throws DaoJpaException {
        // TODO
    }
}

我只能想到两个CDI范围:

  1. @SessionScope : 对我来说,这似乎是最合适的范围,因为单个实例专用于活动会话。
  2. @Dependent : 也是合理的,因为这样的实例将适合将被注入的对象的生命周期。
  3. 在我看来,所有其他CDI范围都不合适:

    1. @ApplicationScoped :由于应用程序作用域存储库每次只创建一次,因此像entityManager.clear()这样的调用将导致所有当前会话的所有实例也将被分离。此外,此单个存储库必须处理所有传入请求。可能这个范围适用于只读存储库吗?
    2. @RequestScope :我认为每个传入请求都不需要新的存储库实例。
    3. @ConversionScoped :转化通常在GUI层实施。如果我希望存储库在转换结束后死亡,我可以将其定义为@Dependent
    4. 那么,这个问题是否有任何已知的最佳实践?

2 个答案:

答案 0 :(得分:3)

描述所有选项

  • 会话范围实际上没有意义,因为您的存储库应该是无状态的,因此会话对它没有任何意义(尽管它会解决并发问题
  • 依赖范围可能是一个不错的选择,但它可能导致内存泄漏(您永远无法确定从内存中删除依赖对象的内容)
  • 会话范围也没有任何意义,它与会话范围
  • 的情况相同

所以我会选择

  • 请求范围 - 我会说这是最好的选择,它的性质是无状态的,所以你将避免任何并发问题。另外,不要担心性能,在新JVM中真正快速地创建新对象
  • 应用程序范围也可能是一个不错的选择,但是您需要担心并发问题(多个客户端同时调用相同的方法)。

所以如果我是你,我会选择Request scope存储库,这是最容易的选择,你会避免所有这些问题。

答案 1 :(得分:1)

您应该使用@ApplicationScoped。

每个请求都应该使用EntityManager,而不是重复使用。

在请求开始时,您创建了entityManager,当它完成提交或回滚时。

@Dependent将具有与其主机相同的范围,如果您将其注入@RequestScoped并且bean具有相同的范围。

@SessionScoped只能用于小数据(如用户登录和权限)。