【发布时间】:2012-12-12 06:50:25
【问题描述】:
我需要在每次数据库操作之前设置一些上下文(我曾尝试使用 Oracle 的包级变量,但由于包重新编译的一些问题,我将尝试使用 DBMS_SESSION 和/或DBMS_APPLICATION_INFO),这样我们就可以在任何我们需要的地方(过程、触发器等)获取特定的用户信息,而不是将数十个数据库连接标识为“JBoss”。
我编写了一个 Java EE 拦截器,用于拦截对 @Stateless bean 的调用。它调用一个 Oracle 函数来设置一些会话上下文(查看这个问题以获取一些示例代码 How to tell if a transaction is active in a Java EE 6 interceptor)。
我首先担心的是连接池。起初我认为 Java EE 提供的默认 @PersistenceContext 传播足以保证一切都在同一个连接/事务/EntityManager 中运行,我只需要在拦截器末尾取消设置所有内容(在finally块)在连接返回到池之前。它看起来有点脆弱,但我认为它可以工作。
然后我发现Hibernate有一个属性叫hibernate.connection.release_mode (Hibernate docs about hibernate.connection.release_mode, Red Hat docs about org.hibernate.ConnectionReleaseMode) 并且使用 JTA 事务时的默认和推荐行为是在每个语句之后释放连接(尽管文档说了一些关于 重新获取相同的底层连接,这让我很困惑)。
现在我什至不确定我是否可以在拦截器中可靠地设置一些内容,这些内容只有该用户/操作才能看到,而不会冒其他人在我的业务方法中间抓住相同连接并弄乱的风险我的用户上下文。据我了解,Oracle 数据库会话变量是为连接保留的,而不是为事务或 @PersistenceContext 保留的(数据库毕竟对持久性上下文一无所知,一个连接可用于多个事务)。
我即将放弃,因为随着我更多地了解所涉及的所有技术的实施细节,这看起来越来越脆弱。 这个用户上下文的想法是否可行,或者我应该尝试一种完全不同的方法?我如何测试/调试我的实现以确保没有任何并发问题?我还没有找到任何有用的事件侦听器来监视框架行为,并构建一个程序来对服务器进行压力测试投资于我不确定是否应该工作的东西太多了。
我正在使用 JBoss AS 7.1、EJB 3.1、Oracle 10g 数据库和 JPA 2.0(由 Hibernate 提供支持,尽管我们不使用任何特定于 Hibernate 的 API)。
【问题讨论】:
-
我想我会避免这种事情,因为它很容易出错,但最好了解幕后发生的事情。 David Blevins (stackoverflow.com/questions/269186/…) 建议 release_mode=after_statement 只是一个“不要费心管理已经管理的内容”的设置,这可以解释说“(...)重新获取相同的底层 JDBC 连接(。 ..)”
-
现在发生在我身上的事情:也许 release_mode 默认是“after_statement”,这样程序员就可以在同一个事务中使用 JPA 和 JDBC 调用,而无需使用两个单独的连接?
-
所以我终于发现了 为什么 release_mode=after_statement 被添加并且需要成为 JTA 事务中的默认值:mail-archive.com/hibernate-dev@lists.jboss.org/msg00612.html (tl;dr: 因为有些容器可能会认为 Hibernate如果它在嵌套的 EJB 调用中打开一个连接并使其保持打开状态以供调用者重用,则会泄漏连接)。我仍然不能完全确定假设没有其他人会重用 JPA 语句之间的连接是否安全。
标签: oracle hibernate jakarta-ee jpa jboss7.x