【问题标题】:EntityManager Lifecycle when using Oracle's Virtual Private Database使用 Oracle 的虚拟专用数据库时的 EntityManager 生命周期
【发布时间】:2011-10-15 08:27:03
【问题描述】:

我有几个问题都与在应用程序中创建和使用实体管理器的方式有关,Virtual Private Databases 是 Oracle DB 中启用行级安全性的一个特性。

  1. 在会话 bean 中,我们通常将实体管理器作为成员,并且它通常由容器注入。这个实体管理器是如何由容器管理的——我的意思是,如果我们想实现一个Virtual Private Database,那么我们必须确保Virtual Private Database-context 在整个用户会话中保持有效,并且我们不必设置这个上下文每次在我们触发查询之前。 (在这里包括更多的废话:一个会话 bean 实现了几个函数,每个函数都使用相同的实体管理器;现在,我们不应该每次都在这些函数中设置虚拟私有数据库数据库操作)。

  2. 进一步#1,由于实体管理器缓存在会话bean中,我们是否需要在任何情况下显式关闭实体管理器? (就像我们对 JDBC 连接所做的那样?)

  3. 另外,我想知道使用 JTA 或非 JTA 数据源的用例(或设计标准)应该是什么。我们创建实体管理器的方式是否依赖于此?

要添加对 VPD 的要求: 如果容器管理的 EM 能够以某种方式强制执行每个用户的 VPD,那就太好了。请注意,此处注入了 EM,因此应该有一种机制可以在连接上设置 VPD(稍后在“this”会话中为“this”用户检索相同的连接)。

如果没有注入的 EM,我认为可以使用对 EMF 的引用然后设置 EM 的属性。就像是 : ((org.eclipse.persistence.internal.jpa.EntityManagerImpl)em.getDelegate()).setProperties

如果每次触发查询之前都设置了 VPD,那么连接应该在用户会话期间“维护”VPD 上下文,然后将连接(在清除 VPD 之后)释放回池.

【问题讨论】:

    标签: oracle jakarta-ee jpa ejb entitymanager


    【解决方案1】:

    在会话 bean 中,注入的实体管理器是容器管理的,默认情况下是事务范围的。

    这意味着当您在会话 bean 上调用任何方法并启动事务时,实体管理器的持久性上下文就会启动。当事务被提交或回滚时,它就结束了。因此,您无需显式关闭实体管理器。

    此外,当已经有一个事务在进行中时,默认情况下会加入该事务,并且当已经有一个持久性上下文附加到所述事务时,它会传播而不是创建一个新的。

    有状态会话 bean 有另一个选项,那就是 extended persistence context。这与有状态 bean 的范围耦合,而不是与单个事务耦合。您仍然不必在这里关闭自己。

    然后,您还可以注入一个EntityManagerFactory(使用@PersistenceUnit),然后从中获取一个实体管理器:在这种情况下,您将拥有一个application managed entity manager。在这种情况下,您必须明确关闭它。

    JTA 数据源(事务性数据源)默认与容器管理的实体管理器一起使用。容器负责这里的一切。非 JTA 数据源适用于您需要单独连接到数据库的情况,可能在任何正在运行的事务之外,您可以自行设置自动提交模式、提交、回滚等。

    可以在 orm.xml 中为持久性单元定义这两种不同的数据源类型。如果您使用非 JTA 数据源定义持久性单元,您通常会使用工厂为其创建实体管理器,然后自行管理所有内容。

    更新:

    关于Virtual Private Database,您似乎需要的是每个实体管理器的用户特定连接,但正常的处理方式是将持久性单元耦合到通用数据源。我想这里可能需要一个在请求连接时知道用户上下文的数据源。

    如果您完全绕过容器,甚至在很大程度上绕过 JPA 抽象,您可以直接进入 Hibernate。它具有您可以在全球范围内注册的提供商,例如 DriverManagerConnectionProviderDatasourceConnectionProvider。如果您通过实际连接的设置器为这些提供自己的实现,则可以在使用它之前从特定实体管理器实例中询问它们,然后在其中设置您自己的连接。

    这是可行的,但不用说有点hacky。希望其他人可以给出更“官方”的答案。如果 Oracle 提供官方插件,例如EclipseLink 支持这一点。 This document 暗示确实如此:

    TopLink / EclipseLink : 支持通过他们的过滤数据 @AdditionalCriteria 注释和 XML。这允许任意 JPQL 要附加到实体的所有查询的片段。片段 可以包含可以通过持久性单元设置的参数或 运行时的上下文属性。还支持 Oracle VPD,包括 Oracle 代理身份验证和隔离数据。

    另见How to use EclipseLink JPA with Oracle Proxy Authentication

    【讨论】:

    • 感谢您对 JTA 和非 JTA DS 的解释。它为我净化了空气。我试图更好地理解“扩展持久性上下文”的使用;在我们的应用程序中,我们没有任何事务,但我们希望 EM 在用户会话期间保持其行为 - 即,当用户触发他的第一个查询时,在此之前需要设置 VPD。这个 EM 句柄应该用于用户会话的其余部分。扩展的持久性上下文是否解决了这个用例?
    • 另外,能否分享一下EntityManagerFactory是如何注入的?
    • 很遗憾,我不知道 VDP(虚拟显示处理?)是什么,所以恐怕我无法帮助您解决这部分问题。我认为不应该特别需要明确地保留实体管理器的行为,即它实际上没有任何行为要保留。例如。 entityManager.find(12, Foo.class) 将始终返回 ID 为 12 的 Foo 实例。此处无需自定义。抱歉,如果我误解了您的用例。
    • >扩展持久性上下文是否解决了这个用例? - 只要有状态 bean 存在,扩展的持久性上下文将主要保持上下文打开。将其设置为会话范围是可能的,但很危险。持久性上下文会记住它遇到的所有实体,除非您非常小心,否则您很可能会很快耗尽内存。
    • VPD - 虚拟专用数据库。它是 Oracle DB 中的一项功能,可启用行级安全性。为此,我需要在用户登录时设置 VPD 上下文,并且在他注销时应清除此上下文。因此,如果您看到 EM 只需要获取已为 this 用户设置 VPD 的特定数据库连接。
    猜你喜欢
    • 2018-05-08
    • 2010-11-06
    • 2015-04-21
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    相关资源
    最近更新 更多