如何在创建 Hibernate 会话时拦截所有会话(Spring / Grails 环境)
有没有办法在创建新的 Hibernate 会话时拦截它们?我需要访问每个 Session 实例以启用带有参数的 Hibernate 过滤器。
我得到的唯一解决方案涉及包装 SessionFactory,但这涉及到许多半令人讨厌的黑客行为,并且需要我实现大约 60 个方法,其中只有少数是有趣的。
Hibernate 的 SessionFactory 实现由于某些烦人的原因被声明为最终的,因此扩展它不是一个选择。我也尝试过方面和 Java 代理,但没有任何运气。
Is there a way of intercepting all new Hibernate sessions when they're created? I need to access each Session instance to enable a Hibernate filter with a parameter.
The only solution I've gotten working has involved wrapping the SessionFactory, but this involved a lot of semi nasty hacks as well as it required me to implement around 60 methods, where only a few are interesting.
Hibernate's SessionFactory implementation is for some annoying reason declared final so extending it is not an option. I've also tried aspects and Java proxies without any luck.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我能够创建一个 JDK 代理:
并且您可以从自定义 SessionFactoryBean 调用它:
这取决于 Spring 的 SpringSessionContext 的修改版本,它使用代理而不是真正的会话工厂:
这需要在 resources.groovy 中注册以替换标准 Grails ConfigurableLocalSessionFactoryBean:
I was able to create a JDK proxy:
and you would call this from a custom SessionFactoryBean:
which depends on a modified version of Spring's SpringSessionContext that uses the proxy instead of the real session factory:
This needs to be registered in resources.groovy to replace the standard Grails ConfigurableLocalSessionFactoryBean:
我已经解决了这个问题(至少在 Hibernate 为此类事情提供适当的 API 之前)。解决方案的简短版本:
更长的版本:
http://www.developer-b.com/blog/entry/1635/2010/oct/07/intercepting-hibernate-sessions
来源/Github:
http://github.com/multi-tenant/grails-hibernate-hijacker (仍然处于实验阶段)
感谢您的投入!
I've solved this problem (at least until Hibernate provides a proper API for things like this). Short version of the solution:
Longer version:
http://www.developer-b.com/blog/entry/1635/2010/oct/07/intercepting-hibernate-sessions
Sources / Github:
http://github.com/multi-tenant/grails-hibernate-hijacker (still very experimental)
Thanks for the input!
伯特和金布尔的答案都有效,但您可以更轻松地做到这一点。您确实需要创建一个实现 Hibernate CurrentSessionContext 类的类,但不需要为会话工厂创建代理,因为您可以覆盖会话上下文类中的会话创建行为,然后只需指定该类的名称即可在会话工厂 bean 的属性中。例如,像这样编写您的会话上下文
然后在传递给会话工厂类的属性中,指定该类名称:
例如,在典型的 Spring 场景中,您可以使用 Spring 工厂 bean 来实例化您的 hibernate 属性,如下所示:
然后通常,您将使用 Spring 会话工厂 bean 创建会话工厂,例如(注意不同版本的 Hibernate 的包名称会有所不同):
Hibernate 包含三个不同的会话上下文类,因此只需覆盖与您相关的一个:
所有三个都有方法 buildOrObtainSession,该方法的 javadoc 实际上说“为子类化目的而提供”。如果您使用跨越多个资源(例如多个数据库或数据库和 JMS 队列)的事务,则需要 JTA 会话上下文,如果您仅在每个事务中访问单个资源,则 ThreadLocalSessionContext 就足够了。
Both Burt and Kimble's answers will work, but you can do this more easily. You do need to create a class that implements the Hibernate CurrentSessionContext class, but there is no need to create a proxy for the session factory, as you can override the session creation behaviour in the session context class, then simply specify the name of this class in the properties to your session factory bean. e.g. write your session context like this
Then in the properties you pass to your session factory class, specify this class name:
For example, in a typical Spring scenario, you might use a Spring factory bean to instantiate your hibernate properties, like this:
Then typically you'll create a session factory using a Spring session factory bean, such as (note package name will differ for different versions of Hibernate):
Hibernate includes three different session context classes, so just override the one relevant to you:
All three have the method buildOrObtainSession, and the javadoc for the method actually says "provided for subclassing purposes". A JTA session context will be required if you are using transactions that span multiple resources, such as multiple databases, or databases and JMS queues, if you are just accessing a single resource in each transaction, a ThreadLocalSessionContext would be sufficient.
看一下 Hibernate-filter 插件 - 这可能就是您想要使用的或者你至少可以看看这个插件是如何做到的。
我还相信 多租户插件 可能有一些使用 Hibernate Session 过滤器的代码。
Take a Look at the Hibernate-filter plugin - this may be what you want to use or you can at least see how that plugin does it.
Also I believe that the Multi-tenant plugin may have some code that uses Hibernate Session filters.
在代码中只有一个位置(例如在 DAO 的抽象基类中)请求一个新会话并在那里启用过滤器可能是最干净的。
It would probably cleanest to have only one place in code where you request a new session from hibernate (for instance in an abstract base class of your DAOs), and enable your filter there.