我需要在每次数据库操作之前设置一些上下文(我曾尝试使用 Oracle 的包级变量,但由于包重新编译的一些问题,我将尝试使用DBMS_SESSION和/或DBMS_APPLICATION_INFO),以便我们可以在任何地方获取特定的用户信息我们需要它(过程、触发器等),而不是将数十个数据库连接标识为“JBoss”。
我编写了一个 Java EE 拦截器来拦截对 @Stateless bean 的调用。它调用一个 Oracle 函数来设置一些会话上下文(查看这个问题以获取一些示例代码如何判断事务是否在 Java EE 6 拦截器中处于活动状态)。
我首先担心的是连接池。起初我认为 Java EE 提供的默认 @PersistenceContext 传播足以保证一切都在同一个连接/事务/EntityManager 中运行,而我只需要在拦截器结束时取消设置所有内容(在一个finally
块中)之前连接返回到池中。它似乎有点脆弱,但我认为它可以工作。
然后我发现 Hibernate 有一个名为 hibernate.connection.release_mode 的属性 (关于 hibernate.connection.release_mode 的 Hibernate 文档,关于 org.hibernate.ConnectionReleaseMode 的 Red Hat 文档)并且使用 JTA 事务时的默认和推荐行为是释放每个语句之后的连接(尽管文档说了一些关于重新获取相同的底层连接,这让我很困惑)。
现在我什至不确定我是否可以在拦截器中可靠地设置一些内容,这些内容只对这个用户/操作可见,而不会有其他人在我的业务方法中间抓住相同的连接并弄乱我的用户上下文的风险. 据我了解,Oracle 数据库会话变量是为连接保留的,而不是为事务或 @PersistenceContext (数据库毕竟对持久性上下文一无所知,并且一个连接可用于多个事务)。
我即将放弃,因为随着我对所涉及的所有技术的实现细节的了解越来越多,这看起来越来越脆弱。可以使这个用户上下文的想法起作用还是我应该尝试一种完全不同的方法?我如何测试/调试我的实现以确保没有任何并发问题?我还没有找到任何有用的事件监听器来监视框架行为,并且构建一个程序来对服务器进行压力测试是太多的工作,无法投资于我不确定是否应该工作的东西。
我正在使用 JBoss AS 7.1、EJB 3.1、Oracle 10g 数据库和 JPA 2.0(由 Hibernate 支持,尽管我们不使用任何特定于 Hibernate 的 API)。