在JPA连接中设置上下文 - 这样安全吗? [英] Setting context in a JPA connection — is this safe?

查看:166
本文介绍了在JPA连接中设置上下文 - 这样安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在每次数据库操作之前设置一些上下文(我已经尝试过使用Oracle的包级变量,但是由于包重新编译的一些问题,我将试验 DBMS_SESSION 和/或 DBMS_APPLICATION_INFO ),以便我们可以在任何需要的地方获取特定的用户信息(程序,触发器等),而不是将数十个数据库连接标识为JBoss。

I need to set some context before every database operation (I have tried using Oracle's package-level variables, but due to some issues with package recompilation, I will experiment with DBMS_SESSION and/or DBMS_APPLICATION_INFO), so that we can get specific user info anywhere we need it (procedures, triggers, etc.), instead of having dozens of database connections identified as "JBoss".

我编写了一个拦截对@Stateless bean的调用的Java EE拦截器。它调用Oracle函数来设置一些会话上下文(查看这个问题以获取一些示例代码如何判断事务是否在Java EE 6拦截器中处于活动状态

I have written a Java EE interceptor that intercepts calls to a @Stateless bean. It calls an Oracle function to set some session context (look at this question for some sample code How to tell if a transaction is active in a Java EE 6 interceptor).

我的第一个担忧是连接池。起初我认为Java EE提供的默认@PersistenceContext传播足以保证一切都在同一个连接/事务/ EntityManager中运行,我只需要在拦截器的末尾取消设置所有内容(在<$ c中)在连接返回池之前,$ c> finally block)。它似乎有点脆弱,但我认为它可以工作。

My first worry was connection pooling. At first I thought that the default @PersistenceContext propagation provided by Java EE would be enough to guarantee that everything runs in the same connection/transaction/EntityManager, and I only had to unset everything at the end of my interceptor (in a finally block) before the connection is returned to the pool. It seemed a little fragile, but I thought it could work.

然后我发现Hibernate有一个名为hibernate.connection.release_mode的属性
Hibernate docs关于hibernate.connection.release_mode 关于org.hibernate.ConnectionReleaseMode的Red Hat文档)以及使用JTA事务时默认和推荐的行为是在每个语句后释放连接(虽然文档说的是重新获取相同的基础连接,这让我很困惑)。

Then I found out that Hibernate has a property called hibernate.connection.release_mode (Hibernate docs about hibernate.connection.release_mode, Red Hat docs about org.hibernate.ConnectionReleaseMode) and that the default and recommended behavior when using JTA transactions is to release the connection after every statement (although the docs say something about re-acquiring the same underlying connection, which just confused me).

现在我'我甚至不确定我能否在拦截器中可靠地设置一些东西l仅对此用户/操作可见,而没有其他人在我的业务方法中抓取相同连接并弄乱我的用户上下文的风险。据我了解,Oracle数据库会话变量是为连接而不是为事务或@PersistenceContext保留的(毕竟数据库对持久化上下文一无所知,并且连接可以用于多个事务)。

Now I'm not even sure I can reliably set something in an interceptor that will be visible only to this user/operation without the risk of somebody else grabbing the same connection in the middle of my business method and making a mess with my user context. As I understand it, Oracle database session variables are kept for a connection, not for a transaction or a @PersistenceContext (the database knows nothing about the persistence context after all, and a connection can be used for multiple transactions).

我即将放弃,因为随着我对所涉及的所有技术的实施细节的了解越来越多,这看起来越来越脆弱。 这个用户上下文的想法是否可以实现,或者我应该尝试完全不同的方法?我怎么能测试/调试我的实现,以确保没有潜伏的并发问题?我没有找到任何有用的事件监听器来监视框架行为,并构建一个程序来压力测试服务器投入一些我不确定应该工作的东西是太多的工作。

I'm about to give up because this is looking more and more fragile as I learn more about the implementation details of all the technologies involved. Can this user context idea be made to work or should I try a totally different approach? And how could I test/debug my implementation to be sure there aren't any concurrency issues lurking around? I haven't found any useful event listener to monitor the framework behavior, and building a program to stress test the server is too much work to invest in something I'm not sure is supposed to work anyway.

我正在使用JBoss AS 7.1,EJB 3.1,一个Oracle 10g数据库,和JPA 2.0(由Hibernate支持,虽然我们不使用任何特定于Hibernate的API)。

I'm using JBoss AS 7.1, EJB 3.1, an Oracle 10g database, and JPA 2.0 (backed by Hibernate, although we do not use any Hibernate-specific API).

推荐答案

所以我会回答我最近发现的所有事情都有自己的问题。

So I'll answer my own question with all the things I have found out lately.

为了理解服务器行为,我改变了我的JBoss配置,只使用了一个连接池,所以我可以检测到其他人何时被阻止等待。

In order to understand server behavior, I changed my JBoss configuration to use a pool of only 1 connection, so I could detect when somebody else is blocked waiting.

如果当前操作在事务内(例如@TransactionAttribute(REQUIRED)),则该连接将不会用于交易完成之前的其他任何事情(其他客户将不得不等待)。但是,如果您在没有事务的情况下读取数据库,则其他客户端可以在您不使用它时获取相同的连接,甚至在您的业务方法完成之前(我不知道这种行为中有多少是标准的,以及实现了多少)详细信息)。

If the current operation is inside a transaction (e.g. @TransactionAttribute(REQUIRED)), the connection won't be used for anything else until the transaction finishes (other clients will have to wait). However, if you read the database without a transaction, other clients could grab the same connection while you are not using it, even before your business method finishes (I don't know how much of this behavior is standard and how much is an implementation detail).

默认情况下,Hibernate会在每个语句之后释放连接,这就是为什么可以在非事务性方法中重用连接的原因。另一方面,如果您仍处于同一事务中,则JDBC和JEE具有重新获取相同连接所需的功能。

Hibernate does release the connection after every statement by default and that's why the connection can be reused in a non-transactional method. On the other hand, JDBC and JEE have the features needed to re-acquire the same connection if you are still in the same transaction.

但为什么Hibernate会释放连接它将在以后重新获得?如果Hibernate没有发布它,一些JEE服务器可能会认为Hibernate在嵌套EJB调用中打开连接时会泄漏连接,并使其打开以供调用者重用。这篇文章对此进行了解释:

But why does Hibernate release a connection that it's going to re-acquire later? If Hibernate didn't release it, some JEE servers could think that Hibernate is leaking connections when it opens a connection in a nested EJB call and leaves it open for the caller to reuse. That is explained in this post:

http://www.mail-archive.com/hibernate-dev@lists.jboss.org/msg00612.html

为了安全起见,我们需要保存的所有数据(以及后来呈现给用户的数据)显式作为参数传递,但出于记录目的,我们确实使用了存储在Oracle会话中的一些数据,因为知道连接无法重用只要您使用交易业务方法,其他客户就可以使用。

To be safe, all data we need to save (and later present to the user) is explicitly passed as parameters, but for logging purposes we did use some data stored in the Oracle session, knowing that the connection cannot be reused by other clients as long as you use transactional business methods.

更新:似乎可以使用某些应用服务器执行我想要的操作与连接器和/或自定义数据源相关的特定设置(不确定这里的最佳答案是什么: https:/ /developer.jboss.org/thread/250132

Update: It seems to be possible to do what I want using some app server specific settings related to connectors and/or custom data sources (not sure what is the best answer here: https://developer.jboss.org/thread/250132)

这篇关于在JPA连接中设置上下文 - 这样安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆