JPA存储库应该首选哪个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范围:

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

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


    描述所有选项

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

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


    你应该使用@ApplicationScoped。

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

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

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

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

    链接地址: http://www.djcxy.com/p/62211.html

    上一篇: Which CDI scope should be preferred for a JPA repository

    下一篇: JSF/CDI session scoped bean corruption