我有一些问题都涉及在Virtual Private Databases
的应用程序中创建和使用实体管理器的方式,这是Oracle DB中启用行级安全性的一项功能。
在会话bean中,我们通常将实体管理器作为成员,并且通常由容器注入。该实体管理器如何由容器管理 - 我的意思是,如果我们想要实现Virtual Private Database
,那么我们必须确保Virtual Private Database
- 上下文对整个用户会话仍然有效,我们这样做在我们触发查询之前,不必每次都设置此上下文。 (在这里包含更多的措辞:会话bean实现了几个函数,并且每个函数都使用相同的实体管理器;现在,我们不应该每次在这些函数中设置虚拟专用数据库数据库操作)。
继#1之后,由于实体管理器缓存在会话bean中,我们是否需要在任何场景中显式关闭实体管理器? (就像我们为JDBC连接做的那样?)
此外,我想知道使用JTA或非JTA数据源的用例(或设计标准)应该是什么。我们创建依赖于此的实体管理器的方式是什么?
在VPD上添加w.r.t的要求: 如果以某种方式管理EM的容器可以强制执行每个用户的VPD,那将是很好的。请注意,EM是在这里注入的,因此应该有一种机制来在连接上设置VPD(稍后在'this'会话中为'this'用户检索相同的连接)。
如果没有注入EM,我认为使用对EMF的引用,然后可以设置EM的属性。就像是 : ((org.eclipse.persistence.internal.jpa.EntityManagerImpl)em.getDelegate())。setProperties方法
如果在查询被触发之前每次都设置了VPD,那么这将是一种过度杀伤,而是连接应该在用户会话期间“维护”VPD上下文,然后将连接(在清除VPD之后)释放回池中
答案 0 :(得分:2)
在会话bean中,注入的实体管理器是容器管理的,默认情况下是事务范围。
这意味着当您调用会话bean上的任何方法并启动事务时,实体管理器的持久性上下文将启动。当提交或回滚事务时,它结束。因此,没有必须明确关闭实体管理器的情况。
此外,当已经存在正在进行的事务时,默认情况下会加入该事务,并且当已经存在附加到所述事务的持久性上下文时,它将被传播而不是正在创建的新事务。
有状态会话bean有另一个选项,那就是extended persistence context
。这个与有状态bean的范围相关联,而不是与单个事务相关联。你仍然不需要在这里做任何关闭。
然后,您还可以注入EntityManagerFactory
(使用@PersistenceUnit),然后从中获取实体管理员:在这种情况下,您将拥有application managed entity manager
。在这种情况下,您必须明确关闭它。
默认情况下,JTA数据源(事务数据源)与容器管理的实体管理器一起使用。容器在这里处理所有事情。非JTA数据源适用于需要与数据库单独连接的情况,可能在任何正在运行的事务之外,您可以在其上设置自动提交模式,提交,回滚等等。
可以在orm.xml中为持久性单元定义这两种不同的数据源类型。如果您使用非JTA数据源定义持久性单元,通常使用工厂为其创建实体管理器,然后管理您自己的所有内容。
<强>更新强>
关于Virtual Private Database
,您在这里需要的是每个实体管理器的用户特定连接,但正常的做法是将持久性单元耦合到通用数据源。我想这里需要的是一个数据源,它在请求连接时知道用户的上下文。
如果你完全绕过容器甚至在很大程度上绕过JPA抽象,你可以直接进入Hibernate。它有一些提供商,您可以在全球注册,如DriverManagerConnectionProvider
和DatasourceConnectionProvider
。如果您使用实际连接的setter为这些实现提供自己的实现,您可以在使用它之前从特定的实体管理器实例中回复它们,然后在其中设置您自己的连接。
这是可行的,但不用说有点hacky。希望其他人可以提供更“官方”的答案。如果Oracle提供了一个官方插件,那么当然是最好的。 EclipseLink支持这一点。 This document暗示它确实:
TopLink / EclipseLink:支持通过他们的过滤数据 @AdditionalCriteria注释和XML。这允许任意JPQL 要附加到实体的所有查询的片段。片段 可以包含可以通过持久性单元设置的参数 运行时的上下文属性。 Oracle VPD也受支持,包括 Oracle代理身份验证和隔离数据。
另见How to use EclipseLink JPA with Oracle Proxy Authentication。